Minor, cleanup InlineTestUtil.kt
This commit is contained in:
@@ -23,16 +23,14 @@ import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
|||||||
import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass
|
import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass
|
||||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
|
||||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||||
import org.jetbrains.org.objectweb.asm.*
|
import org.jetbrains.org.objectweb.asm.*
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.properties.Delegates
|
|
||||||
|
|
||||||
object InlineTestUtil {
|
object InlineTestUtil {
|
||||||
private val KOTLIN_MULTIFILE_CLASS_DESC =
|
private val KOTLIN_MULTIFILE_CLASS_DESC =
|
||||||
"L" + AsmUtil.internalNameByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS) + ";"
|
AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS)
|
||||||
|
|
||||||
fun checkNoCallsToInline(files: Iterable<OutputFile>, sourceFiles: List<KtFile>) {
|
fun checkNoCallsToInline(files: Iterable<OutputFile>, sourceFiles: List<KtFile>) {
|
||||||
val inlineInfo = obtainInlineInfo(files)
|
val inlineInfo = obtainInlineInfo(files)
|
||||||
@@ -42,16 +40,16 @@ object InlineTestUtil {
|
|||||||
val notInlinedCalls = checkInlineMethodNotInvoked(files, inlineMethods)
|
val notInlinedCalls = checkInlineMethodNotInvoked(files, inlineMethods)
|
||||||
assert(notInlinedCalls.isEmpty()) { "All inline methods should be inlined but:\n" + notInlinedCalls.joinToString("\n") }
|
assert(notInlinedCalls.isEmpty()) { "All inline methods should be inlined but:\n" + notInlinedCalls.joinToString("\n") }
|
||||||
|
|
||||||
|
val skipParameterChecking = sourceFiles.any {
|
||||||
val skipParameterChecking =
|
InTextDirectivesUtils.isDirectiveDefined(it.text, "NO_CHECK_LAMBDA_INLINING")
|
||||||
sourceFiles.asSequence().filter {
|
}
|
||||||
InTextDirectivesUtils.isDirectiveDefined(it.text, "NO_CHECK_LAMBDA_INLINING")
|
|
||||||
}.any()
|
|
||||||
|
|
||||||
if (!skipParameterChecking) {
|
if (!skipParameterChecking) {
|
||||||
val notInlinedParameters = checkParametersInlined(files, inlineInfo)
|
val notInlinedParameters = checkParametersInlined(files, inlineInfo)
|
||||||
assert(notInlinedParameters.isEmpty()) { "All inline parameters should be inlined but:\n${notInlinedParameters.joinToString("\n")}\n" +
|
assert(notInlinedParameters.isEmpty()) {
|
||||||
"but if you have not inlined lambdas or anonymous objects enable NO_CHECK_LAMBDA_INLINING directive" }
|
"All inline parameters should be inlined but:\n${notInlinedParameters.joinToString("\n")}\n" +
|
||||||
|
"but if you have not inlined lambdas or anonymous objects enable NO_CHECK_LAMBDA_INLINING directive"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +108,7 @@ object InlineTestUtil {
|
|||||||
if (inlinedMethods.contains(methodCall)) {
|
if (inlinedMethods.contains(methodCall)) {
|
||||||
val fromCall = MethodInfo(className, this.name, this.desc)
|
val fromCall = MethodInfo(className, this.name, this.desc)
|
||||||
|
|
||||||
//skip delegation to trait impl from child class
|
//skip delegation to interface DefaultImpls from child class
|
||||||
if (methodCall.owner.endsWith(JvmAbi.DEFAULT_IMPLS_SUFFIX) && fromCall.owner != methodCall.owner) {
|
if (methodCall.owner.endsWith(JvmAbi.DEFAULT_IMPLS_SUFFIX) && fromCall.owner != methodCall.owner) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -129,42 +127,37 @@ object InlineTestUtil {
|
|||||||
val inlinedMethods = inlineInfo.inlineMethods
|
val inlinedMethods = inlineInfo.inlineMethods
|
||||||
val notInlinedParameters = ArrayList<NotInlinedParameter>()
|
val notInlinedParameters = ArrayList<NotInlinedParameter>()
|
||||||
for (file in files) {
|
for (file in files) {
|
||||||
val kotlinClassHeader = getClassHeader(file)
|
if (!isClassOrPackagePartKind(getClassHeader(file))) continue
|
||||||
if (isClassOrPackagePartKind(kotlinClassHeader)) {
|
|
||||||
val cr = ClassReader(file.asByteArray())
|
|
||||||
|
|
||||||
cr.accept(object : ClassVisitorWithName() {
|
ClassReader(file.asByteArray()).accept(object : ClassVisitorWithName() {
|
||||||
|
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor? {
|
||||||
|
val declaration = MethodInfo(className, name, desc)
|
||||||
|
//do not check anonymous object creation in inline functions and in package facades
|
||||||
|
if (declaration in inlinedMethods) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor? {
|
return object : MethodNode(Opcodes.ASM5, access, name, desc, signature, exceptions) {
|
||||||
JvmClassName.byInternalName(className).fqNameForClassNameWithoutDollars
|
private fun isInlineParameterLikeOwner(owner: String) =
|
||||||
val declaration = MethodInfo(className, name, desc)
|
"$" in owner && !isTopLevelOrInnerOrPackageClass(owner, inlineInfo)
|
||||||
//do not check anonymous object creation in inline functions and in package facades
|
|
||||||
if (declaration in inlinedMethods) {
|
override fun visitMethodInsn(opcode: Int, owner: String, name: String, desc: String, itf: Boolean) {
|
||||||
return null
|
if ("<init>".equals(name) && isInlineParameterLikeOwner(owner)) {
|
||||||
|
val fromCall = MethodInfo(className, this.name, this.desc)
|
||||||
|
notInlinedParameters.add(NotInlinedParameter(owner, fromCall))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return object : MethodNode(Opcodes.ASM5, access, name, desc, signature, exceptions) {
|
override fun visitFieldInsn(opcode: Int, owner: String, name: String, desc: String) {
|
||||||
private fun isInlineParameterLikeOwner(owner: String) = owner.contains("$") && !isTopLevelOrInnerOrPackageClass(owner, inlineInfo)
|
if (opcode == Opcodes.GETSTATIC && isInlineParameterLikeOwner(owner)) {
|
||||||
|
val fromCall = MethodInfo(className, this.name, this.desc)
|
||||||
override fun visitMethodInsn(opcode: Int, owner: String, name: String, desc: String, itf: Boolean) {
|
notInlinedParameters.add(NotInlinedParameter(owner, fromCall))
|
||||||
if ("<init>".equals(name) && isInlineParameterLikeOwner(owner)) {
|
|
||||||
/*constuctor creation*/
|
|
||||||
val fromCall = MethodInfo(className, this.name, this.desc)
|
|
||||||
notInlinedParameters.add(NotInlinedParameter(owner, fromCall))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitFieldInsn(opcode: Int, owner: String, name: String, desc: String) {
|
|
||||||
if (opcode == Opcodes.GETSTATIC && isInlineParameterLikeOwner(owner)) {
|
|
||||||
val fromCall = MethodInfo(className, this.name, this.desc)
|
|
||||||
notInlinedParameters.add(NotInlinedParameter(owner, fromCall))
|
|
||||||
}
|
|
||||||
super.visitFieldInsn(opcode, owner, name, desc)
|
|
||||||
}
|
}
|
||||||
|
super.visitFieldInsn(opcode, owner, name, desc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 0)
|
}
|
||||||
}
|
}, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
return notInlinedParameters
|
return notInlinedParameters
|
||||||
@@ -202,9 +195,8 @@ object InlineTestUtil {
|
|||||||
|
|
||||||
private data class MethodInfo(val owner: String, val name: String, val desc: String)
|
private data class MethodInfo(val owner: String, val name: String, val desc: String)
|
||||||
|
|
||||||
open private class ClassVisitorWithName() : ClassVisitor(Opcodes.ASM5) {
|
private open class ClassVisitorWithName : ClassVisitor(Opcodes.ASM5) {
|
||||||
|
lateinit var className: String
|
||||||
var className: String by Delegates.notNull()
|
|
||||||
|
|
||||||
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String?, interfaces: Array<String>?) {
|
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String?, interfaces: Array<String>?) {
|
||||||
className = name
|
className = name
|
||||||
|
|||||||
Reference in New Issue
Block a user