11package com.github.codeql
22
3- import com.github.codeql.utils.lowerBound
4- import com.github.codeql.utils.substituteTypeAndArguments
5- import com.github.codeql.utils.upperBound
63import com.semmle.extractor.java.OdasaOutput
74import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
85import org.jetbrains.kotlin.descriptors.ClassKind
@@ -12,10 +9,8 @@ import org.jetbrains.kotlin.ir.IrStatement
129import org.jetbrains.kotlin.ir.declarations.*
1310import org.jetbrains.kotlin.ir.expressions.*
1411import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
15- import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
1612import org.jetbrains.kotlin.ir.types.*
1713import org.jetbrains.kotlin.ir.util.*
18- import org.jetbrains.kotlin.types.Variance
1914
2015open class KotlinFileExtractor (
2116 override val logger : FileLogger ,
@@ -48,7 +43,7 @@ open class KotlinFileExtractor(
4843 is IrClass -> return getClassLabel(element, listOf ()).classLabel
4944 is IrTypeParameter -> return getTypeParameterLabel(element)
5045 is IrFunction -> return getFunctionLabel(element)
51- is IrValueParameter -> return getValueParameterLabel(element, null )
46+ is IrValueParameter -> return getValueParameterLabel(element)
5247 is IrProperty -> return getPropertyLabel(element)
5348 is IrField -> return getFieldLabel(element)
5449 is IrEnumEntry -> return getEnumEntryLabel(element)
@@ -86,7 +81,7 @@ open class KotlinFileExtractor(
8681 return id
8782 }
8883
89- fun extractClassInstance (c : IrClass , typeArgs : List <IrTypeArgument >, extractFunctionPrototypes : Boolean ): Label <out DbClassorinterface > {
84+ fun extractClassInstance (c : IrClass , typeArgs : List <IrTypeArgument >): Label <out DbClassorinterface > {
9085 if (typeArgs.isEmpty()) {
9186 logger.warn(Severity .ErrorSevere , " Instance without type arguments: " + c.name.asString())
9287 }
@@ -127,18 +122,6 @@ open class KotlinFileExtractor(
127122 val locId = tw.getLocation(c)
128123 tw.writeHasLocation(id, locId)
129124
130- if (extractFunctionPrototypes) {
131- val typeParamSubstitution = c.typeParameters.map({ it.symbol }).zip(typeArgs).toMap()
132-
133- c.declarations.map {
134- when (it) {
135- is IrFunction -> extractFunction(it, id, false , typeParamSubstitution)
136- is IrProperty -> extractProperty(it, id, false , typeParamSubstitution)
137- else -> {}
138- }
139- }
140- }
141-
142125 return id
143126 }
144127
@@ -271,12 +254,9 @@ open class KotlinFileExtractor(
271254 return FieldResult (instanceId, instanceName)
272255 }
273256
274- fun extractValueParameter (vp : IrValueParameter , parent : Label <out DbCallable >, idx : Int , typeSubstitutionMap : Map <IrTypeParameterSymbol , IrTypeArgument >? ): TypeResults {
275- val id = useValueParameter(vp, parent)
276- val substitutedType = vp.type.substituteTypeAndArguments(typeSubstitutionMap) {
277- it.lowerBound(pluginContext)
278- }
279- val type = useType(substitutedType)
257+ fun extractValueParameter (vp : IrValueParameter , parent : Label <out DbCallable >, idx : Int ): TypeResults {
258+ val id = useValueParameter(vp)
259+ val type = useType(vp.type)
280260 val locId = tw.getLocation(vp)
281261 tw.writeParams(id, type.javaResult.id, type.kotlinResult.id, idx, parent, id)
282262 tw.writeHasLocation(id, locId)
@@ -351,7 +331,7 @@ open class KotlinFileExtractor(
351331 }
352332 }
353333
354- fun extractFunction (f : IrFunction , parentId : Label <out DbReftype >, extractBody : Boolean = true, typeSubstitutionMap : Map < IrTypeParameterSymbol , IrTypeArgument > ? = null ): Label <out DbCallable > {
334+ fun extractFunction (f : IrFunction , parentId : Label <out DbReftype >): Label <out DbCallable > {
355335 currentFunction = f
356336
357337 f.typeParameters.map { extractTypeParameter(it) }
@@ -362,21 +342,19 @@ open class KotlinFileExtractor(
362342 if (f.isLocalFunction())
363343 getLocalFunctionLabels(f).function
364344 else
365- // TODO: figure out whether to standardise on naming top-level functions for the file-class
366- // or (as temporarily done here) for their containing package.
367- useFunction<DbCallable >(f, if (f.parent is IrFile ) useDeclarationParent(f.parent) else parentId)
345+ useFunction<DbCallable >(f)
368346
369347 val extReceiver = f.extensionReceiverParameter
370348 val idxOffset = if (extReceiver != null ) 1 else 0
371349 val paramTypes = f.valueParameters.mapIndexed { i, vp ->
372- extractValueParameter(vp, id, i + idxOffset, typeSubstitutionMap )
350+ extractValueParameter(vp, id, i + idxOffset)
373351 }
374352 val allParamTypes = if (extReceiver != null ) {
375353 val extendedType = useType(extReceiver.type)
376354 @Suppress(" UNCHECKED_CAST" )
377355 tw.writeKtExtensionFunctions(id as Label <DbMethod >, extendedType.javaResult.id, extendedType.kotlinResult.id)
378356
379- val t = extractValueParameter(extReceiver, id, 0 , null )
357+ val t = extractValueParameter(extReceiver, id, 0 )
380358 val l = mutableListOf (t)
381359 l.addAll(paramTypes)
382360 l
@@ -386,31 +364,21 @@ open class KotlinFileExtractor(
386364
387365 val paramsSignature = allParamTypes.joinToString(separator = " ," , prefix = " (" , postfix = " )" ) { it.javaResult.signature!! }
388366
389- val substReturnType = f.returnType.substituteTypeAndArguments(typeSubstitutionMap) {
390- it.upperBound(pluginContext)
391- }
392-
393367 if (f.symbol is IrConstructorSymbol ) {
394- val unitType = useType(pluginContext.irBuiltIns.unitType, TypeContext .RETURN )
395- val shortName = when {
396- f.returnType.isAnonymous -> " "
397- typeSubstitutionMap != null -> useType(substReturnType).javaResult.shortName
398- else -> f.returnType.classFqName?.shortName()?.asString() ? : f.name.asString()
399- }
368+ val returnType = useType(erase(f.returnType), TypeContext .RETURN )
369+ val shortName = if (f.returnType.isAnonymous) " " else f.returnType.classFqName?.shortName()?.asString() ? : f.name.asString()
400370 @Suppress(" UNCHECKED_CAST" )
401- tw.writeConstrs(id as Label <DbConstructor >, shortName, " $shortName$paramsSignature " , unitType .javaResult.id, unitType .kotlinResult.id, parentId, id)
371+ tw.writeConstrs(id as Label <DbConstructor >, shortName, " $shortName$paramsSignature " , returnType .javaResult.id, returnType .kotlinResult.id, parentId, id)
402372 } else {
403- val returnType = useType(substReturnType , TypeContext .RETURN )
373+ val returnType = useType(f.returnType , TypeContext .RETURN )
404374 val shortName = f.name.asString()
405375 @Suppress(" UNCHECKED_CAST" )
406376 tw.writeMethods(id as Label <DbMethod >, shortName, " $shortName$paramsSignature " , returnType.javaResult.id, returnType.kotlinResult.id, parentId, id)
407377 }
408378
409379 tw.writeHasLocation(id, locId)
410380 val body = f.body
411- if (body != null && extractBody) {
412- if (typeSubstitutionMap != null )
413- logger.warnElement(Severity .ErrorSevere , " Type substitution should only be used to extract a function prototype, not the body" , f)
381+ if (body != null ) {
414382 extractBody(body, id)
415383 }
416384
@@ -427,8 +395,8 @@ open class KotlinFileExtractor(
427395 return id
428396 }
429397
430- fun extractProperty (p : IrProperty , parentId : Label <out DbReftype >, extractBackingField : Boolean = true, typeSubstitutionMap : Map < IrTypeParameterSymbol , IrTypeArgument > ? = null ) {
431- val id = useProperty(p, parentId )
398+ fun extractProperty (p : IrProperty , parentId : Label <out DbReftype >) {
399+ val id = useProperty(p)
432400 val locId = tw.getLocation(p)
433401 tw.writeKtProperties(id, p.name.asString())
434402 tw.writeHasLocation(id, locId)
@@ -439,7 +407,7 @@ open class KotlinFileExtractor(
439407
440408 if (getter != null ) {
441409 @Suppress(" UNCHECKED_CAST" )
442- val getterId = extractFunction(getter, parentId, extractBackingField, typeSubstitutionMap ) as Label <out DbMethod >
410+ val getterId = extractFunction(getter, parentId) as Label <out DbMethod >
443411 tw.writeKtPropertyGetters(id, getterId)
444412 } else {
445413 if (p.modality != Modality .FINAL || ! isExternalDeclaration(p)) {
@@ -452,15 +420,15 @@ open class KotlinFileExtractor(
452420 logger.warnElement(Severity .ErrorSevere , " !isVar property with a setter" , p)
453421 }
454422 @Suppress(" UNCHECKED_CAST" )
455- val setterId = extractFunction(setter, parentId, extractBackingField, typeSubstitutionMap ) as Label <out DbMethod >
423+ val setterId = extractFunction(setter, parentId) as Label <out DbMethod >
456424 tw.writeKtPropertySetters(id, setterId)
457425 } else {
458426 if (p.isVar && ! isExternalDeclaration(p)) {
459427 logger.warnElement(Severity .ErrorSevere , " isVar property without a setter" , p)
460428 }
461429 }
462430
463- if (bf != null && extractBackingField ) {
431+ if (bf != null ) {
464432 val fieldId = extractField(bf, parentId)
465433 tw.writeKtPropertyBackingFields(id, fieldId)
466434 }
@@ -716,16 +684,17 @@ open class KotlinFileExtractor(
716684 isFunction(" kotlin" , " Double" , fName)
717685 }
718686
719- fun extractMethodAccess (callTarget : IrFunction , extractMethodTypeArguments : Boolean = true, extractClassTypeArguments : Boolean = false) {
687+ fun extractMethodAccess (callTarget : IrFunction , extractTypeArguments : Boolean = true) {
720688 val id = tw.getFreshIdLabel<DbMethodaccess >()
721689 val type = useType(c.type)
722690 val locId = tw.getLocation(c)
691+
723692 tw.writeExprs_methodaccess(id, type.javaResult.id, type.kotlinResult.id, parent, idx)
724693 tw.writeHasLocation(id, locId)
725694 tw.writeCallableEnclosingExpr(id, callable)
726695 tw.writeStatementEnclosingExpr(id, enclosingStmt)
727696
728- if (extractMethodTypeArguments ) {
697+ if (extractTypeArguments ) {
729698 // type arguments at index -2, -3, ...
730699 extractTypeArguments(c, id, callable, enclosingStmt, - 2 , true )
731700 }
@@ -744,28 +713,10 @@ open class KotlinFileExtractor(
744713 tw.writeCallableBinding(idNewexpr, ids.constructor )
745714
746715 } else {
747- val dr = c.dispatchReceiver
748-
749- // Returns true if type is C<T1, T2, ...> where C is declared `class <T1, T2, ...> C { ... }`
750- fun isUnspecialised (type : IrSimpleType ) =
751- type.classifier.owner is IrClass &&
752- (type.classifier.owner as IrClass ).typeParameters.zip(type.arguments).all { paramAndArg ->
753- (paramAndArg.second as ? IrTypeProjection )?.let {
754- // Type arg refers to the class' own type parameter?
755- it.variance == Variance .INVARIANT &&
756- it.type.classifierOrNull?.owner == = paramAndArg.first
757- } ? : false
758- }
759-
760- val drType = dr?.type
761- val methodId =
762- if (drType != null && extractClassTypeArguments && drType is IrSimpleType && ! isUnspecialised(drType))
763- useFunction<DbCallable >(callTarget, drType.arguments)
764- else
765- useFunction<DbCallable >(callTarget)
766-
716+ val methodId = useFunction<DbMethod >(callTarget)
767717 tw.writeCallableBinding(id, methodId)
768718
719+ val dr = c.dispatchReceiver
769720 if (dr != null ) {
770721 extractExpressionExpr(dr, callable, id, - 1 , enclosingStmt)
771722 }
@@ -1087,7 +1038,7 @@ open class KotlinFileExtractor(
10871038 }
10881039 }
10891040 else -> {
1090- extractMethodAccess(c.symbol.owner, true , true )
1041+ extractMethodAccess(c.symbol.owner)
10911042 }
10921043 }
10931044 }
@@ -1136,7 +1087,7 @@ open class KotlinFileExtractor(
11361087 type = useType(e.type)
11371088 }
11381089 val locId = tw.getLocation(e)
1139- val methodId = useFunction<DbConstructor >(e.symbol.owner, (e.type as ? IrSimpleType )?.arguments )
1090+ val methodId = useFunction<DbConstructor >(e.symbol.owner)
11401091 tw.writeExprs_newexpr(id, type.javaResult.id, type.kotlinResult.id, parent, idx)
11411092 tw.writeHasLocation(id, locId)
11421093 tw.writeCallableEnclosingExpr(id, callable)
0 commit comments