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()
}
}