/* * Copyright 2017-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ package kotlinx.atomicfu.transformer import org.objectweb.asm.tree.AbstractInsnNode import org.objectweb.asm.tree.InsnList import java.io.File import org.slf4j.LoggerFactory abstract class AtomicFUTransformerBase( var inputDir: File, var outputDir: File ) { protected operator fun File.div(child: String) = File(this, child) protected fun File.toOutputFile(): File = outputDir / relativeTo(inputDir).toString() private val logger = LoggerFactory.getLogger(this::class.java) protected fun File.mkdirsAndWrite(outBytes: ByteArray) { parentFile.mkdirs() writeBytes(outBytes) // write resulting bytes } protected fun File.isClassFile() = toString().endsWith(".class") var verbose = true protected var lastError: Throwable? = null protected var transformed = false data class SourceInfo( val method: MethodId, val source: String?, val i: AbstractInsnNode? = null, val insnList: InsnList? = null ) { override fun toString(): String = buildString { source?.let { append("$it:") } i?.line?.let { append("$it:") } append(" $method") } } private fun format(message: String, sourceInfo: SourceInfo? = null): String { var loc = if (sourceInfo == null) "" else sourceInfo.toString() + ": " if (verbose && sourceInfo != null && sourceInfo.i != null) loc += sourceInfo.i.atIndex(sourceInfo.insnList) return "$loc$message" } protected fun info(message: String, sourceInfo: SourceInfo? = null) { logger.info(format(message, sourceInfo)) } protected fun debug(message: String, sourceInfo: SourceInfo? = null) { logger.debug(format(message, sourceInfo)) } protected fun error(message: String, sourceInfo: SourceInfo? = null) { logger.error(format(message, sourceInfo)) if (lastError == null) lastError = TransformerException(message) } abstract fun transform() } class TransformerException(message: String, cause: Throwable? = null) : Exception(message, cause)