@@ -6,6 +6,7 @@ import com.github.codeql.utils.versions.functionN
66import com.github.codeql.utils.versions.getIrStubFromDescriptor
77import com.semmle.extractor.java.OdasaOutput
88import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
9+ import org.jetbrains.kotlin.backend.common.lower.parents
910import org.jetbrains.kotlin.backend.common.pop
1011import org.jetbrains.kotlin.builtins.functions.BuiltInFunctionArity
1112import org.jetbrains.kotlin.descriptors.*
@@ -314,8 +315,21 @@ open class KotlinFileExtractor(
314315 val locId = getLocation(c, argsIncludingOuterClasses)
315316 tw.writeHasLocation(id, locId)
316317
317- // Extract the outer <-> inner class relationship, passing on any type arguments in excess to this class' parameters.
318- extractEnclosingClass(c, id, locId, argsIncludingOuterClasses?.drop(c.typeParameters.size) ? : listOf ())
318+ // Extract the outer <-> inner class relationship, passing on any type arguments in excess to this class' parameters if this is an inner class.
319+ // For example, in `class Outer<T> { inner class Inner<S> { } }`, `Inner<Int, String>` nests within `Outer<Int>` and raw `Inner<>` within `Outer<>`,
320+ // but for a similar non-`inner` (in Java terms, static nested) class both `Inner<Int>` and `Inner<>` nest within the unbound type `Outer`.
321+ val useBoundOuterType = (c.isInner || c.isLocal) && (c.parents.firstNotNullOfOrNull {
322+ when (it) {
323+ is IrClass -> when {
324+ it.typeParameters.isNotEmpty() -> true // Type parameters visible to this class -- extract an enclosing bound or raw type.
325+ ! (it.isInner || it.isLocal) -> false // No type parameters seen yet, and this is a static class -- extract an enclosing unbound type.
326+ else -> null // No type parameters seen here, but may be visible enclosing type parameters; keep searching.
327+ }
328+ else -> null // Look through enclosing non-class entities (this may need to change)
329+ }
330+ } ? : false )
331+
332+ extractEnclosingClass(c, id, locId, if (useBoundOuterType) argsIncludingOuterClasses?.drop(c.typeParameters.size) else listOf ())
319333
320334 return id
321335 }
@@ -458,7 +472,8 @@ open class KotlinFileExtractor(
458472 }
459473 }
460474
461- private fun extractEnclosingClass (innerDeclaration : IrDeclaration , innerId : Label <out DbClassorinterface >, innerLocId : Label <DbLocation >, parentClassTypeArguments : List <IrTypeArgument >) {
475+ // If `parentClassTypeArguments` is null, the parent class is a raw type.
476+ private fun extractEnclosingClass (innerDeclaration : IrDeclaration , innerId : Label <out DbClassorinterface >, innerLocId : Label <DbLocation >, parentClassTypeArguments : List <IrTypeArgument >? ) {
462477 with (" enclosing class" , innerDeclaration) {
463478 var parent: IrDeclarationParent ? = innerDeclaration.parent
464479 while (parent != null ) {
0 commit comments