Merge pull request #10674 from tamasvajk/kotlin-implements

Kotlin: extract `implInterface`
This commit is contained in:
Tamás Vajk
2022-10-05 09:11:41 +02:00
committed by GitHub
5 changed files with 131 additions and 11 deletions

View File

@@ -266,10 +266,9 @@ open class KotlinFileExtractor(
val pkg = c.packageFqName?.asString() ?: ""
val cls = classLabelResults.shortName
val pkgId = extractPackage(pkg)
val kind = c.kind
// TODO: There's lots of duplication between this and extractClassSource.
// Can we share it?
if(kind == ClassKind.INTERFACE || kind == ClassKind.ANNOTATION_CLASS) {
if (c.isInterfaceLike) {
val interfaceId = id.cast<DbInterface>()
val sourceInterfaceId = useClassSource(c).cast<DbInterface>()
tw.writeInterfaces(interfaceId, cls, pkgId, sourceInterfaceId)
@@ -278,6 +277,7 @@ open class KotlinFileExtractor(
val sourceClassId = useClassSource(c).cast<DbClass>()
tw.writeClasses(classId, cls, pkgId, sourceClassId)
val kind = c.kind
if (kind == ClassKind.ENUM_CLASS) {
tw.writeIsEnumType(classId)
} else if (kind != ClassKind.CLASS && kind != ClassKind.OBJECT) {
@@ -405,14 +405,14 @@ open class KotlinFileExtractor(
val pkg = c.packageFqName?.asString() ?: ""
val cls = if (c.isAnonymousObject) "" else c.name.asString()
val pkgId = extractPackage(pkg)
val kind = c.kind
if (kind == ClassKind.INTERFACE || kind == ClassKind.ANNOTATION_CLASS) {
if (c.isInterfaceLike) {
val interfaceId = id.cast<DbInterface>()
tw.writeInterfaces(interfaceId, cls, pkgId, interfaceId)
} else {
val classId = id.cast<DbClass>()
tw.writeClasses(classId, cls, pkgId, classId)
val kind = c.kind
if (kind == ClassKind.ENUM_CLASS) {
tw.writeIsEnumType(classId)
} else if (kind != ClassKind.CLASS && kind != ClassKind.OBJECT) {
@@ -4955,7 +4955,7 @@ open class KotlinFileExtractor(
addModifiers(id, "final")
addVisibilityModifierToLocalOrAnonymousClass(id)
extractClassSupertypes(superTypes, listOf(), id, inReceiverContext = true)
extractClassSupertypes(superTypes, listOf(), id, isInterface = false, inReceiverContext = true)
extractEnclosingClass(declarationParent, id, null, locId, listOf())

View File

@@ -1496,10 +1496,10 @@ open class KotlinUsesExtractor(
* Argument `inReceiverContext` will be passed onto the `useClassInstance` invocation for each supertype.
*/
fun extractClassSupertypes(c: IrClass, id: Label<out DbReftype>, mode: ExtractSupertypesMode = ExtractSupertypesMode.Unbound, inReceiverContext: Boolean = false) {
extractClassSupertypes(c.superTypes, c.typeParameters, id, mode, inReceiverContext)
extractClassSupertypes(c.superTypes, c.typeParameters, id, c.isInterfaceLike, mode, inReceiverContext)
}
fun extractClassSupertypes(superTypes: List<IrType>, typeParameters: List<IrTypeParameter>, id: Label<out DbReftype>, mode: ExtractSupertypesMode = ExtractSupertypesMode.Unbound, inReceiverContext: Boolean = false) {
fun extractClassSupertypes(superTypes: List<IrType>, typeParameters: List<IrTypeParameter>, id: Label<out DbReftype>, isInterface: Boolean, mode: ExtractSupertypesMode = ExtractSupertypesMode.Unbound, inReceiverContext: Boolean = false) {
// Note we only need to substitute type args here because it is illegal to directly extend a type variable.
// (For example, we can't have `class A<E> : E`, but can have `class A<E> : Comparable<E>`)
val subbedSupertypes = when(mode) {
@@ -1514,12 +1514,15 @@ open class KotlinUsesExtractor(
for(t in subbedSupertypes) {
when(t) {
is IrSimpleType -> {
val owner = t.classifier.owner
when (owner) {
when (val owner = t.classifier.owner) {
is IrClass -> {
val typeArgs = if (t.arguments.isNotEmpty() && mode is ExtractSupertypesMode.Raw) null else t.arguments
val l = useClassInstance(owner, typeArgs, inReceiverContext).typeResult.id
tw.writeExtendsReftype(id, l)
if (isInterface || !owner.isInterfaceLike) {
tw.writeExtendsReftype(id, l)
} else {
tw.writeImplInterface(id.cast(), l.cast())
}
}
else -> {
logger.error("Unexpected simple type supertype: " + t.javaClass + ": " + t.render())

View File

@@ -1,8 +1,12 @@
package com.github.codeql.utils
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFunction
fun IrFunction.isLocalFunction(): Boolean {
return this.visibility == DescriptorVisibilities.LOCAL
}
}
val IrClass.isInterfaceLike get() = kind == ClassKind.INTERFACE || kind == ClassKind.ANNOTATION_CLASS