/*
 * Copyright 2010-2024 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.
 */

// This file was generated automatically. See compiler/ir/ir.tree/tree-generator/ReadMe.md.
// DO NOT MODIFY IT MANUALLY.

package org.jetbrains.kotlin.ir.util

import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.visitors.IrTypeVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid

/**
 * Auto-generated by [org.jetbrains.kotlin.ir.generator.print.IrTreeSymbolsVisitorPrinter]
 */
abstract class IrTreeSymbolsVisitor : IrTypeVisitorVoid(), SymbolVisitor {

    override fun visitType(container: IrElement, type: IrType) {
        type.classifierOrNull?.let { visitSymbol(container, it) }
    }

    override fun visitAnnotationUsage(annotationUsage: IrConstructorCall) {
        visitReferencedConstructor(annotationUsage, annotationUsage.symbol)
        visitTypeRecursively(annotationUsage, annotationUsage.type)
        visitElement(annotationUsage)
    }

    override fun visitElement(element: IrElement) {
        element.acceptChildrenVoid(this)
    }

    override fun visitDeclaration(declaration: IrDeclarationBase) {
        declaration.annotations.forEach { visitAnnotationUsage(it) }
        visitElement(declaration)
    }

    override fun visitValueParameter(declaration: IrValueParameter) {
        visitDeclaredValueParameter(declaration, declaration.symbol)
        declaration.varargElementType?.let { visitTypeRecursively(declaration, it) }
        visitTypeRecursively(declaration, declaration.type)
        visitDeclaration(declaration)
    }

    override fun visitClass(declaration: IrClass) {
        visitDeclaredClass(declaration, declaration.symbol)
        declaration.sealedSubclasses.forEach { visitReferencedClass(declaration, it) }
        declaration.valueClassRepresentation?.mapUnderlyingType {
            visitTypeRecursively(declaration, it)
            it
        }
        declaration.superTypes.forEach { visitTypeRecursively(declaration, it) }
        visitDeclaration(declaration)
    }

    override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer) {
        visitDeclaredAnonymousInitializer(declaration, declaration.symbol)
        visitDeclaration(declaration)
    }

    override fun visitTypeParameter(declaration: IrTypeParameter) {
        visitDeclaredTypeParameter(declaration, declaration.symbol)
        declaration.superTypes.forEach { visitTypeRecursively(declaration, it) }
        visitDeclaration(declaration)
    }

    override fun visitFunction(declaration: IrFunction) {
        visitTypeRecursively(declaration, declaration.returnType)
        visitDeclaration(declaration)
    }

    override fun visitConstructor(declaration: IrConstructor) {
        visitDeclaredConstructor(declaration, declaration.symbol)
        visitFunction(declaration)
    }

    override fun visitEnumEntry(declaration: IrEnumEntry) {
        visitDeclaredEnumEntry(declaration, declaration.symbol)
        visitDeclaration(declaration)
    }

    override fun visitField(declaration: IrField) {
        visitDeclaredField(declaration, declaration.symbol)
        declaration.correspondingPropertySymbol?.let { visitReferencedProperty(declaration, it) }
        visitTypeRecursively(declaration, declaration.type)
        visitDeclaration(declaration)
    }

    override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty) {
        visitDeclaredLocalDelegatedProperty(declaration, declaration.symbol)
        visitTypeRecursively(declaration, declaration.type)
        visitDeclaration(declaration)
    }

    override fun visitModuleFragment(declaration: IrModuleFragment) {
        visitElement(declaration)
    }

    override fun visitProperty(declaration: IrProperty) {
        visitDeclaredProperty(declaration, declaration.symbol)
        declaration.overriddenSymbols.forEach { visitReferencedProperty(declaration, it) }
        visitDeclaration(declaration)
    }

    override fun visitScript(declaration: IrScript) {
        visitDeclaredScript(declaration, declaration.symbol)
        declaration.providedProperties.forEach { visitReferencedProperty(declaration, it) }
        declaration.resultProperty?.let { visitReferencedProperty(declaration, it) }
        declaration.importedScripts?.forEach { visitReferencedScript(declaration, it) }
        declaration.earlierScripts?.forEach { visitReferencedScript(declaration, it) }
        declaration.targetClass?.let { visitReferencedClass(declaration, it) }
        declaration.baseClass?.let { visitTypeRecursively(declaration, it) }
        visitDeclaration(declaration)
    }

    override fun visitReplSnippet(declaration: IrReplSnippet) {
        visitDeclaredReplSnippet(declaration, declaration.symbol)
        declaration.stateObject?.let { visitReferencedClass(declaration, it) }
        declaration.targetClass?.let { visitReferencedClass(declaration, it) }
        declaration.returnType?.let { visitTypeRecursively(declaration, it) }
        visitDeclaration(declaration)
    }

    override fun visitSimpleFunction(declaration: IrSimpleFunction) {
        visitDeclaredSimpleFunction(declaration, declaration.symbol)
        declaration.overriddenSymbols.forEach { visitReferencedSimpleFunction(declaration, it) }
        declaration.correspondingPropertySymbol?.let { visitReferencedProperty(declaration, it) }
        visitFunction(declaration)
    }

    override fun visitTypeAlias(declaration: IrTypeAlias) {
        visitDeclaredTypeAlias(declaration, declaration.symbol)
        visitTypeRecursively(declaration, declaration.expandedType)
        visitDeclaration(declaration)
    }

    override fun visitVariable(declaration: IrVariable) {
        visitDeclaredVariable(declaration, declaration.symbol)
        visitTypeRecursively(declaration, declaration.type)
        visitDeclaration(declaration)
    }

    override fun visitPackageFragment(declaration: IrPackageFragment) {
        visitElement(declaration)
    }

    override fun visitExternalPackageFragment(declaration: IrExternalPackageFragment) {
        visitDeclaredExternalPackageFragment(declaration, declaration.symbol)
        visitPackageFragment(declaration)
    }

    override fun visitFile(declaration: IrFile) {
        declaration.annotations.forEach { visitAnnotationUsage(it) }
        visitDeclaredFile(declaration, declaration.symbol)
        visitPackageFragment(declaration)
    }

    override fun visitExpression(expression: IrExpression) {
        visitTypeRecursively(expression, expression.type)
        visitElement(expression)
    }

    override fun visitBody(body: IrBody) {
        visitElement(body)
    }

    override fun visitExpressionBody(body: IrExpressionBody) {
        visitBody(body)
    }

    override fun visitBlockBody(body: IrBlockBody) {
        visitBody(body)
    }

    override fun visitDeclarationReference(expression: IrDeclarationReference) {
        visitExpression(expression)
    }

    override fun visitMemberAccess(expression: IrMemberAccessExpression<*>) {
        for (type in expression.typeArguments) {
            if (type != null) {
                visitTypeRecursively(expression, type)
            }
        }
        visitDeclarationReference(expression)
    }

    override fun visitFunctionAccess(expression: IrFunctionAccessExpression) {
        visitMemberAccess(expression)
    }

    override fun visitConstructorCall(expression: IrConstructorCall) {
        visitReferencedConstructor(expression, expression.symbol)
        visitFunctionAccess(expression)
    }

    override fun visitSingletonReference(expression: IrGetSingletonValue) {
        visitDeclarationReference(expression)
    }

    override fun visitGetObjectValue(expression: IrGetObjectValue) {
        visitReferencedClass(expression, expression.symbol)
        visitSingletonReference(expression)
    }

    override fun visitGetEnumValue(expression: IrGetEnumValue) {
        visitReferencedEnumEntry(expression, expression.symbol)
        visitSingletonReference(expression)
    }

    override fun visitRawFunctionReference(expression: IrRawFunctionReference) {
        visitReferencedFunction(expression, expression.symbol)
        visitDeclarationReference(expression)
    }

    override fun visitContainerExpression(expression: IrContainerExpression) {
        visitExpression(expression)
    }

    override fun visitBlock(expression: IrBlock) {
        visitContainerExpression(expression)
    }

    override fun visitComposite(expression: IrComposite) {
        visitContainerExpression(expression)
    }

    override fun visitReturnableBlock(expression: IrReturnableBlock) {
        visitDeclaredReturnableBlock(expression, expression.symbol)
        visitBlock(expression)
    }

    override fun visitInlinedFunctionBlock(inlinedBlock: IrInlinedFunctionBlock) {
        inlinedBlock.inlinedFunctionSymbol?.let { visitReferencedFunction(inlinedBlock, it) }
        visitBlock(inlinedBlock)
    }

    override fun visitSyntheticBody(body: IrSyntheticBody) {
        visitBody(body)
    }

    override fun visitBreakContinue(jump: IrBreakContinue) {
        visitExpression(jump)
    }

    override fun visitBreak(jump: IrBreak) {
        visitBreakContinue(jump)
    }

    override fun visitContinue(jump: IrContinue) {
        visitBreakContinue(jump)
    }

    override fun visitCall(expression: IrCall) {
        visitReferencedSimpleFunction(expression, expression.symbol)
        expression.superQualifierSymbol?.let { visitReferencedClass(expression, it) }
        visitFunctionAccess(expression)
    }

    override fun visitCallableReference(expression: IrCallableReference<*>) {
        visitMemberAccess(expression)
    }

    override fun visitFunctionReference(expression: IrFunctionReference) {
        expression.reflectionTarget?.let { visitReferencedFunction(expression, it) }
        visitReferencedFunction(expression, expression.symbol)
        visitCallableReference(expression)
    }

    override fun visitPropertyReference(expression: IrPropertyReference) {
        expression.field?.let { visitReferencedField(expression, it) }
        expression.getter?.let { visitReferencedSimpleFunction(expression, it) }
        expression.setter?.let { visitReferencedSimpleFunction(expression, it) }
        visitReferencedProperty(expression, expression.symbol)
        visitCallableReference(expression)
    }

    override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference) {
        visitReferencedVariable(expression, expression.delegate)
        visitReferencedSimpleFunction(expression, expression.getter)
        expression.setter?.let { visitReferencedSimpleFunction(expression, it) }
        visitReferencedLocalDelegatedProperty(expression, expression.symbol)
        visitCallableReference(expression)
    }

    override fun visitRichCallableReference(expression: IrRichCallableReference<*>) {
        visitExpression(expression)
    }

    override fun visitRichFunctionReference(expression: IrRichFunctionReference) {
        visitReferencedSimpleFunction(expression, expression.overriddenFunctionSymbol)
        visitRichCallableReference(expression)
    }

    override fun visitRichPropertyReference(expression: IrRichPropertyReference) {
        visitRichCallableReference(expression)
    }

    override fun visitClassReference(expression: IrClassReference) {
        visitReferencedClassifier(expression, expression.symbol)
        visitTypeRecursively(expression, expression.classType)
        visitDeclarationReference(expression)
    }

    override fun visitConst(expression: IrConst) {
        visitExpression(expression)
    }

    override fun visitConstantValue(expression: IrConstantValue) {
        visitExpression(expression)
    }

    override fun visitConstantPrimitive(expression: IrConstantPrimitive) {
        visitConstantValue(expression)
    }

    override fun visitConstantObject(expression: IrConstantObject) {
        visitReferencedConstructor(expression, expression.constructor)
        expression.typeArguments.forEach { visitTypeRecursively(expression, it) }
        visitConstantValue(expression)
    }

    override fun visitConstantArray(expression: IrConstantArray) {
        visitConstantValue(expression)
    }

    override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) {
        visitReferencedConstructor(expression, expression.symbol)
        visitFunctionAccess(expression)
    }

    override fun visitDynamicExpression(expression: IrDynamicExpression) {
        visitExpression(expression)
    }

    override fun visitDynamicOperatorExpression(expression: IrDynamicOperatorExpression) {
        visitDynamicExpression(expression)
    }

    override fun visitDynamicMemberExpression(expression: IrDynamicMemberExpression) {
        visitDynamicExpression(expression)
    }

    override fun visitEnumConstructorCall(expression: IrEnumConstructorCall) {
        visitReferencedConstructor(expression, expression.symbol)
        visitFunctionAccess(expression)
    }

    override fun visitErrorExpression(expression: IrErrorExpression) {
        visitExpression(expression)
    }

    override fun visitErrorCallExpression(expression: IrErrorCallExpression) {
        visitErrorExpression(expression)
    }

    override fun visitFieldAccess(expression: IrFieldAccessExpression) {
        visitDeclarationReference(expression)
    }

    override fun visitGetField(expression: IrGetField) {
        visitFieldAccess(expression)
    }

    override fun visitSetField(expression: IrSetField) {
        visitFieldAccess(expression)
    }

    override fun visitFunctionExpression(expression: IrFunctionExpression) {
        visitExpression(expression)
    }

    override fun visitGetClass(expression: IrGetClass) {
        visitExpression(expression)
    }

    override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall) {
        visitReferencedClass(expression, expression.classSymbol)
        visitExpression(expression)
    }

    override fun visitLoop(loop: IrLoop) {
        visitExpression(loop)
    }

    override fun visitWhileLoop(loop: IrWhileLoop) {
        visitLoop(loop)
    }

    override fun visitDoWhileLoop(loop: IrDoWhileLoop) {
        visitLoop(loop)
    }

    override fun visitReturn(expression: IrReturn) {
        visitReferencedReturnTarget(expression, expression.returnTargetSymbol)
        visitExpression(expression)
    }

    override fun visitStringConcatenation(expression: IrStringConcatenation) {
        visitExpression(expression)
    }

    override fun visitSuspensionPoint(expression: IrSuspensionPoint) {
        visitExpression(expression)
    }

    override fun visitSuspendableExpression(expression: IrSuspendableExpression) {
        visitExpression(expression)
    }

    override fun visitThrow(expression: IrThrow) {
        visitExpression(expression)
    }

    override fun visitTry(aTry: IrTry) {
        visitExpression(aTry)
    }

    override fun visitCatch(aCatch: IrCatch) {
        visitElement(aCatch)
    }

    override fun visitTypeOperator(expression: IrTypeOperatorCall) {
        visitTypeRecursively(expression, expression.typeOperand)
        visitExpression(expression)
    }

    override fun visitValueAccess(expression: IrValueAccessExpression) {
        visitDeclarationReference(expression)
    }

    override fun visitGetValue(expression: IrGetValue) {
        visitValueAccess(expression)
    }

    override fun visitSetValue(expression: IrSetValue) {
        visitValueAccess(expression)
    }

    override fun visitVararg(expression: IrVararg) {
        visitTypeRecursively(expression, expression.varargElementType)
        visitExpression(expression)
    }

    override fun visitSpreadElement(spread: IrSpreadElement) {
        visitElement(spread)
    }

    override fun visitWhen(expression: IrWhen) {
        visitExpression(expression)
    }

    override fun visitBranch(branch: IrBranch) {
        visitElement(branch)
    }

    override fun visitElseBranch(branch: IrElseBranch) {
        visitBranch(branch)
    }
}
