Kotlin: extract implInterface

This commit is contained in:
Tamas Vajk
2022-10-04 13:11:55 +02:00
parent d50be83f57
commit d2861361d9
4 changed files with 41 additions and 34 deletions

View File

@@ -264,10 +264,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)
@@ -276,6 +275,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) {
@@ -403,14 +403,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) {
@@ -4775,7 +4775,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

@@ -1489,10 +1489,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) {
@@ -1507,12 +1507,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

View File

@@ -7,8 +7,8 @@ extendsOrImplements
| classes.kt:20:1:22:1 | IF1 | file://<external>/Object.class:0:0:0:0 | Object | extends |
| classes.kt:24:1:26:1 | IF2 | file://<external>/Object.class:0:0:0:0 | Object | extends |
| classes.kt:28:1:30:1 | ClassSix | classes.kt:12:1:15:1 | ClassFour | extends |
| classes.kt:28:1:30:1 | ClassSix | classes.kt:20:1:22:1 | IF1 | extends |
| classes.kt:28:1:30:1 | ClassSix | classes.kt:24:1:26:1 | IF2 | extends |
| classes.kt:28:1:30:1 | ClassSix | classes.kt:20:1:22:1 | IF1 | implements |
| classes.kt:28:1:30:1 | ClassSix | classes.kt:24:1:26:1 | IF2 | implements |
| classes.kt:34:1:47:1 | ClassSeven | file://<external>/Object.class:0:0:0:0 | Object | extends |
| classes.kt:49:1:51:1 | Direction | file://<external>/Enum.class:0:0:0:0 | Enum<Direction> | extends |
| classes.kt:53:1:57:1 | Color | file://<external>/Enum.class:0:0:0:0 | Enum<Color> | extends |
@@ -16,17 +16,17 @@ extendsOrImplements
| classes.kt:60:1:60:23 | Interface2 | file://<external>/Object.class:0:0:0:0 | Object | extends |
| classes.kt:61:1:61:26 | Interface3 | file://<external>/Object.class:0:0:0:0 | Object | extends |
| classes.kt:63:1:91:1 | Class1 | file://<external>/Object.class:0:0:0:0 | Object | extends |
| classes.kt:66:20:66:54 | new Object(...) { ... } | classes.kt:59:1:59:23 | Interface1 | extends |
| classes.kt:66:20:66:54 | new Object(...) { ... } | classes.kt:60:1:60:23 | Interface2 | extends |
| classes.kt:68:20:68:74 | new Object(...) { ... } | classes.kt:59:1:59:23 | Interface1 | extends |
| classes.kt:68:20:68:74 | new Object(...) { ... } | classes.kt:60:1:60:23 | Interface2 | extends |
| classes.kt:68:20:68:74 | new Object(...) { ... } | file://<external>/Interface3.class:0:0:0:0 | Interface3<String> | extends |
| classes.kt:72:16:77:10 | new Object(...) { ... } | classes.kt:59:1:59:23 | Interface1 | extends |
| classes.kt:72:16:77:10 | new Object(...) { ... } | classes.kt:60:1:60:23 | Interface2 | extends |
| classes.kt:66:20:66:54 | new Object(...) { ... } | classes.kt:59:1:59:23 | Interface1 | implements |
| classes.kt:66:20:66:54 | new Object(...) { ... } | classes.kt:60:1:60:23 | Interface2 | implements |
| classes.kt:68:20:68:74 | new Object(...) { ... } | classes.kt:59:1:59:23 | Interface1 | implements |
| classes.kt:68:20:68:74 | new Object(...) { ... } | classes.kt:60:1:60:23 | Interface2 | implements |
| classes.kt:68:20:68:74 | new Object(...) { ... } | file://<external>/Interface3.class:0:0:0:0 | Interface3<String> | implements |
| classes.kt:72:16:77:10 | new Object(...) { ... } | classes.kt:59:1:59:23 | Interface1 | implements |
| classes.kt:72:16:77:10 | new Object(...) { ... } | classes.kt:60:1:60:23 | Interface2 | implements |
| classes.kt:75:24:75:33 | new Object(...) { ... } | file://<external>/Object.class:0:0:0:0 | Object | extends |
| classes.kt:81:16:81:38 | new Interface1(...) { ... } | classes.kt:59:1:59:23 | Interface1 | extends |
| classes.kt:81:16:81:38 | new Interface1(...) { ... } | classes.kt:59:1:59:23 | Interface1 | implements |
| classes.kt:85:16:85:25 | new Object(...) { ... } | file://<external>/Object.class:0:0:0:0 | Object | extends |
| classes.kt:89:16:89:44 | new Interface3<Integer>(...) { ... } | file://<external>/Interface3.class:0:0:0:0 | Interface3<Integer> | extends |
| classes.kt:89:16:89:44 | new Interface3<Integer>(...) { ... } | file://<external>/Interface3.class:0:0:0:0 | Interface3<Integer> | implements |
| classes.kt:93:1:93:26 | pulicClass | file://<external>/Object.class:0:0:0:0 | Object | extends |
| classes.kt:94:1:94:29 | privateClass | file://<external>/Object.class:0:0:0:0 | Object | extends |
| classes.kt:95:1:95:31 | internalClass | file://<external>/Object.class:0:0:0:0 | Object | extends |
@@ -73,31 +73,31 @@ extendsOrImplements
| generic_anonymous.kt:16:5:18:5 | C0 | file://<external>/Object.class:0:0:0:0 | Object | extends |
| generic_anonymous.kt:20:5:22:5 | C1 | file://<external>/Object.class:0:0:0:0 | Object | extends |
| generic_anonymous.kt:25:9:31:9 | | file://<external>/Object.class:0:0:0:0 | Object | extends |
| generic_anonymous.kt:26:13:26:37 | new Object(...) { ... } | file://<external>/Outer$C0.class:0:0:0:0 | C0<U2> | extends |
| generic_anonymous.kt:26:13:26:37 | new Object(...) { ... } | file://<external>/Outer$C1.class:0:0:0:0 | C1<U3> | extends |
| generic_anonymous.kt:27:13:27:37 | new Object(...) { ... } | file://<external>/Outer$C0.class:0:0:0:0 | C0<U2> | extends |
| generic_anonymous.kt:27:13:27:37 | new Object(...) { ... } | file://<external>/Outer$C1.class:0:0:0:0 | C1<U2> | extends |
| generic_anonymous.kt:28:13:28:41 | new Object(...) { ... } | file://<external>/Outer$C0.class:0:0:0:0 | C0<U2> | extends |
| generic_anonymous.kt:28:13:28:41 | new Object(...) { ... } | file://<external>/Outer$C1.class:0:0:0:0 | C1<String> | extends |
| generic_anonymous.kt:29:13:29:29 | new C0<U2>(...) { ... } | file://<external>/Outer$C0.class:0:0:0:0 | C0<U2> | extends |
| generic_anonymous.kt:30:13:30:33 | new C0<String>(...) { ... } | file://<external>/Outer$C0.class:0:0:0:0 | C0<String> | extends |
| generic_anonymous.kt:26:13:26:37 | new Object(...) { ... } | file://<external>/Outer$C0.class:0:0:0:0 | C0<U2> | implements |
| generic_anonymous.kt:26:13:26:37 | new Object(...) { ... } | file://<external>/Outer$C1.class:0:0:0:0 | C1<U3> | implements |
| generic_anonymous.kt:27:13:27:37 | new Object(...) { ... } | file://<external>/Outer$C0.class:0:0:0:0 | C0<U2> | implements |
| generic_anonymous.kt:27:13:27:37 | new Object(...) { ... } | file://<external>/Outer$C1.class:0:0:0:0 | C1<U2> | implements |
| generic_anonymous.kt:28:13:28:41 | new Object(...) { ... } | file://<external>/Outer$C0.class:0:0:0:0 | C0<U2> | implements |
| generic_anonymous.kt:28:13:28:41 | new Object(...) { ... } | file://<external>/Outer$C1.class:0:0:0:0 | C1<String> | implements |
| generic_anonymous.kt:29:13:29:29 | new C0<U2>(...) { ... } | file://<external>/Outer$C0.class:0:0:0:0 | C0<U2> | implements |
| generic_anonymous.kt:30:13:30:33 | new C0<String>(...) { ... } | file://<external>/Outer$C0.class:0:0:0:0 | C0<String> | implements |
| localClassField.kt:1:1:11:1 | A | file://<external>/Object.class:0:0:0:0 | Object | extends |
| localClassField.kt:3:9:3:19 | L | file://<external>/Object.class:0:0:0:0 | Object | extends |
| localClassField.kt:8:9:8:19 | L | file://<external>/Object.class:0:0:0:0 | Object | extends |
| local_anonymous.kt:3:1:36:1 | Class1 | file://<external>/Object.class:0:0:0:0 | Object | extends |
| local_anonymous.kt:5:16:7:9 | new Object(...) { ... } | file://<external>/Object.class:0:0:0:0 | Object | extends |
| local_anonymous.kt:11:9:11:24 | | file://<external>/Object.class:0:0:0:0 | Object | extends |
| local_anonymous.kt:16:23:16:49 | new Function2<Integer,Integer,Integer>(...) { ... } | file://<external>/Function2.class:0:0:0:0 | Function2<Integer,Integer,Integer> | extends |
| local_anonymous.kt:16:23:16:49 | new Function2<Integer,Integer,Integer>(...) { ... } | file://<external>/Function2.class:0:0:0:0 | Function2<Integer,Integer,Integer> | implements |
| local_anonymous.kt:16:23:16:49 | new Function2<Integer,Integer,Integer>(...) { ... } | file://<external>/Object.class:0:0:0:0 | Object | extends |
| local_anonymous.kt:17:23:17:49 | new Function2<Integer,Integer,Integer>(...) { ... } | file://<external>/Function2.class:0:0:0:0 | Function2<Integer,Integer,Integer> | extends |
| local_anonymous.kt:17:23:17:49 | new Function2<Integer,Integer,Integer>(...) { ... } | file://<external>/Function2.class:0:0:0:0 | Function2<Integer,Integer,Integer> | implements |
| local_anonymous.kt:17:23:17:49 | new Function2<Integer,Integer,Integer>(...) { ... } | file://<external>/Object.class:0:0:0:0 | Object | extends |
| local_anonymous.kt:21:21:21:31 | new Function1<Class1,Unit>(...) { ... } | file://<external>/Function1.class:0:0:0:0 | Function1<Class1,Unit> | extends |
| local_anonymous.kt:21:21:21:31 | new Function1<Class1,Unit>(...) { ... } | file://<external>/Function1.class:0:0:0:0 | Function1<Class1,Unit> | implements |
| local_anonymous.kt:21:21:21:31 | new Function1<Class1,Unit>(...) { ... } | file://<external>/FunctionReference.class:0:0:0:0 | FunctionReference | extends |
| local_anonymous.kt:25:9:25:27 | LocalClass | file://<external>/Object.class:0:0:0:0 | Object | extends |
| local_anonymous.kt:29:31:35:5 | new Object(...) { ... } | file://<external>/Object.class:0:0:0:0 | Object | extends |
| local_anonymous.kt:38:1:38:23 | Interface2 | file://<external>/Object.class:0:0:0:0 | Object | extends |
| local_anonymous.kt:39:1:45:1 | Class2 | file://<external>/Object.class:0:0:0:0 | Object | extends |
| local_anonymous.kt:40:14:44:5 | new Interface2(...) { ... } | local_anonymous.kt:38:1:38:23 | Interface2 | extends |
| local_anonymous.kt:40:14:44:5 | new Interface2(...) { ... } | local_anonymous.kt:38:1:38:23 | Interface2 | implements |
| superChain.kt:1:1:1:33 | SuperChain1 | file://<external>/Object.class:0:0:0:0 | Object | extends |
| superChain.kt:2:1:2:60 | SuperChain2 | file://<external>/SuperChain1.class:0:0:0:0 | SuperChain1<T3,String> | extends |
| superChain.kt:3:1:3:60 | SuperChain3 | file://<external>/SuperChain2.class:0:0:0:0 | SuperChain2<T5,String> | extends |