override fun visitCall()

in plugins/compose/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/IrSourcePrinter.kt [245:441]


    override fun visitCall(expression: IrCall) {
        val function = expression.symbol.owner
        val name = function.name.asString()
        val isOperator = function.isOperator || function.origin == IrBuiltIns.BUILTIN_OPERATOR
        val isInfix = function.isInfix
        if (isOperator) {
            if (name == "not") {
                // IR tree for `a != b` looks like `not(equals(a, b))` which makes
                // it challenging to print it like the former. To do so, we capture when we are in
                // a "not" call, and then check to see if the argument is an equals call. if it is,
                // we will just print the child call and put the transformer into a mode where it
                // knows to print the negative
                val arg = expression.dispatchReceiver!!
                if (arg is IrCall) {
                    val fn = arg.symbol.owner
                    if (fn.origin == IrBuiltIns.BUILTIN_OPERATOR) {
                        when (fn.name.asString()) {
                            "equals",
                            "EQEQ",
                            "EQEQEQ",
                                -> {
                                val prevIsInNotCall = isInNotCall
                                isInNotCall = true
                                arg.print()
                                isInNotCall = prevIsInNotCall
                                return
                            }
                        }
                    }
                }
            }
            val opSymbol = when (name) {
                "contains" -> "in"
                "equals" -> if (isInNotCall) "!=" else "=="
                "plus" -> "+"
                "not" -> "!"
                "minus" -> "-"
                "times" -> "*"
                "div" -> "/"
                "rem" -> "%"
                "rangeTo" -> ".."
                "plusAssign" -> "+="
                "minusAssign" -> "-="
                "unaryMinus" -> "-"
                "timesAssign" -> "*="
                "divAssign" -> "/="
                "remAssign" -> "%="
                "inc" -> "++"
                "dec" -> "--"
                "greater" -> ">"
                "less" -> "<"
                "lessOrEqual" -> "<="
                "greaterOrEqual" -> ">="
                "EQEQ" -> if (isInNotCall) "!=" else "=="
                "EQEQEQ" -> if (isInNotCall) "!==" else "==="
                "OROR" -> "||"
                "ieee754equals" -> "=="

                // no names for
                "invoke", "get", "set" -> ""
                "iterator", "hasNext", "next", "getValue", "setValue",
                "noWhenBranchMatchedException",
                    -> name
                "CHECK_NOT_NULL" -> "!!"
                "THROW_ISE" -> "throw IllegalStateException()"
                else -> {
                    if (name.startsWith("component")) name
                    else error("Unhandled operator $name")
                }
            }

            val printBinary = when (name) {
                "equals",
                "EQEQ",
                "EQEQEQ",
                    -> {
                    expression.argumentForKind(IrParameterKind.DispatchReceiver)?.type?.isInt() == true ||
                            expression.argumentForKind(IrParameterKind.ExtensionReceiver)?.type?.isInt() == true ||
                            function.namedParameters.let {
                                it.isNotEmpty() &&
                                        expression.arguments[it.first().indexInParameters]?.type?.isInt() == true
                            }
                }
                else -> false
            }
            val prevPrintBinary = printIntsAsBinary
            printIntsAsBinary = printBinary
            when (name) {
                // unary prefx
                "unaryPlus", "unaryMinus", "not" -> {
                    print(opSymbol)
                    expression.printReceiver()
                }
                // unary postfix
                "inc", "dec" -> {
                    expression.printReceiver()
                    print(opSymbol)
                }
                "CHECK_NOT_NULL" -> {
                    expression.arguments[0]?.print()
                    print(opSymbol)
                }
                "getValue", "setValue" -> {
                    expression.printReceiver()
                    print(".")
                    print(opSymbol)
                    expression.printArgumentList()
                }
                "invoke" -> {
                    expression.printReceiver()
                    expression.printArgumentList()
                }
                // get indexer
                "get" -> {
                    expression.printReceiver()
                    print("[")
                    for (i in 0 until expression.arguments.size) {
                        if (function.parameters[i].kind == IrParameterKind.Regular) {
                            val arg = expression.arguments[i]
                            arg?.print()
                        }

                    }
                    print("]")
                }
                // set indexer
                "set" -> {
                    expression.printReceiver()
                    print("[")
                    expression.arguments[function.parameters.first { it.kind == IrParameterKind.Regular }.indexInParameters]?.print()
                    print("] = ")
                    expression.arguments[function.parameters.last { it.kind == IrParameterKind.Regular }.indexInParameters]?.print()
                }
                // builtin static operators
                "greater", "less", "lessOrEqual", "greaterOrEqual", "EQEQ", "EQEQEQ",
                "ieee754equals",
                    -> {
                    expression.arguments[0]?.print()
                    print(" $opSymbol ")
                    expression.arguments[1]?.print()
                }
                "iterator", "hasNext", "next" -> {
                    expression.printReceiver()
                    print(".")
                    print(opSymbol)
                    print("()")
                }
                "THROW_ISE", "noWhenBranchMatchedException" -> {
                    print(opSymbol)
                    print("()")
                }
                else -> {
                    if (name.startsWith("component")) {
                        expression.printReceiver()
                        print(".")
                        print(opSymbol)
                        print("()")
                    } else {
                        // else binary
                        expression.printReceiver()
                        print(" $opSymbol ")
                        expression.printFirstParameter()
                    }
                }
            }
            printIntsAsBinary = prevPrintBinary
            return
        }

        if (isInfix) {
            val prev = printIntsAsBinary
            if (name == "xor" || name == "and" || name == "or") {
                printIntsAsBinary = true
            }
            expression.printReceiver()
            print(" $name ")
            expression.printFirstParameter()
            printIntsAsBinary = prev
            return
        }

        expression.printExplicitReceiver(".", expression.superQualifierSymbol)

        val prop = function.correspondingPropertySymbol?.owner

        if (prop != null && !function.hasComposableAnnotation()) {
            val propName = prop.name.asString()
            print(propName)
            if (function == prop.setter) {
                print(" = ")
                expression.printFirstParameter()
            }
        } else {
            print(name)
            expression.printArgumentList()
        }
    }