diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 1767f331f93..19044880472 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -180,11 +180,20 @@ open class KotlinFileExtractor( return try { val bytes = virtualFile.contentsToByteArray() var found = false + var hasKotlinMetadata = false val reader = org.jetbrains.org.objectweb.asm.ClassReader(bytes) reader.accept( object : org.jetbrains.org.objectweb.asm.ClassVisitor( org.jetbrains.org.objectweb.asm.Opcodes.ASM9 ) { + override fun visitAnnotation( + descriptor: String, + visible: Boolean + ): org.jetbrains.org.objectweb.asm.AnnotationVisitor? { + if (descriptor == "Lkotlin/Metadata;") hasKotlinMetadata = true + return null + } + override fun visitMethod( access: Int, methodName: String, @@ -200,7 +209,7 @@ open class KotlinFileExtractor( org.jetbrains.org.objectweb.asm.ClassReader.SKIP_DEBUG or org.jetbrains.org.objectweb.asm.ClassReader.SKIP_FRAMES ) - found + if (hasKotlinMetadata) false else found } catch (e: Exception) { logger.warn("Failed to check binary class methods for ${c.fqNameWhenAvailable}: $e") null @@ -212,9 +221,29 @@ open class KotlinFileExtractor( private fun isJavaBinaryDeclaration(f: IrFunction) = f.parentClassOrNull?.let { javaBinaryDeclaresMethod(it, f.name.asString()) } ?: false + private fun hasConcreteSiblingObjectMethod(f: IrFunction): Boolean { + val parentClass = f.parentClassOrNull ?: return false + return parentClass.declarations + .asSequence() + .filterIsInstance() + .filter { sibling -> + sibling !== f && + sibling.name == f.name && + sibling.codeQlValueParameters.size == f.codeQlValueParameters.size + } + .any { sibling -> + val hasInvisibleFakeVisibility = + sibling.visibility.let { + it is DelegatedDescriptorVisibility && it.delegate == Visibilities.InvisibleFake + } + !sibling.isFakeOverride && !hasInvisibleFakeVisibility + } + } + private fun isJavaBinaryObjectMethodRedeclaration(d: IrDeclaration) = when (d) { is IrFunction -> + d.parentClassOrNull?.typeParameters?.isEmpty() == true && when (d.name.asString()) { "toString" -> d.codeQlValueParameters.isEmpty() "hashCode" -> d.codeQlValueParameters.isEmpty() @@ -226,7 +255,9 @@ open class KotlinFileExtractor( ?.type ?.let { it.isNullableAny() || it.isAny() } ?: false else -> false - } && isJavaBinaryDeclaration(d) + } && + !hasConcreteSiblingObjectMethod(d) && + isJavaBinaryDeclaration(d) else -> false }