mirror of
https://github.com/github/codeql.git
synced 2026-05-01 03:35:13 +02:00
Kotlin: Add support for objects
This commit is contained in:
@@ -873,18 +873,43 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
}
|
||||
|
||||
val locId = tw.getLocation(c)
|
||||
tw.writeHasLocation(id, locId)
|
||||
|
||||
c.typeParameters.map { extractTypeParameter(it) }
|
||||
c.declarations.map { extractDeclaration(it, id) }
|
||||
extractObjectInitializerFunction(c, id)
|
||||
|
||||
val locId = tw.getLocation(c)
|
||||
tw.writeHasLocation(id, locId)
|
||||
if(c.isObject) {
|
||||
// For `object MyObject { ... }`, the .class has an
|
||||
// automatically-generated `public static final MyObject INSTANCE`
|
||||
// field that may be referenced from Java code, and is used in our
|
||||
// IrGetObjectValue support. We therefore need to fabricate it
|
||||
// here.
|
||||
val instance = useObjectClassInstance(c)
|
||||
val type = useSimpleTypeClass(c, emptyList(), false)
|
||||
tw.writeFields(instance.id, instance.name, type.javaResult.id, type.kotlinResult.id, id, instance.id)
|
||||
tw.writeHasLocation(instance.id, locId)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
tw.writeClass_object(id as Label<DbClass>, instance.id)
|
||||
}
|
||||
|
||||
extractClassCommon(c, id)
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
data class ObjectClassInstance(val id: Label<DbField>, val name: String)
|
||||
fun useObjectClassInstance(c: IrClass): ObjectClassInstance {
|
||||
if(!c.isObject) {
|
||||
logger.warn(Severity.ErrorSevere, "Using instance for non-object class")
|
||||
}
|
||||
val classId = useClassSource(c)
|
||||
val instanceName = "INSTANCE"
|
||||
val instanceLabel = "@\"field;{$classId};$instanceName\""
|
||||
val instanceId: Label<DbField> = tw.getLabelFor(instanceLabel)
|
||||
return ObjectClassInstance(instanceId, instanceName)
|
||||
}
|
||||
|
||||
private fun isQualifiedThis(vp: IrValueParameter): Boolean {
|
||||
return isQualifiedThisFunction(vp) ||
|
||||
isQualifiedThisClass(vp)
|
||||
@@ -1623,6 +1648,22 @@ open class KotlinFileExtractor(
|
||||
val exprParent = parent.expr(e, callable)
|
||||
extractTypeOperatorCall(e, callable, exprParent.parent, exprParent.idx)
|
||||
}
|
||||
is IrGetObjectValue -> {
|
||||
// For `object MyObject { ... }`, the .class has an
|
||||
// automatically-generated `public static final MyObject INSTANCE`
|
||||
// field that we are accessing here.
|
||||
val exprParent = parent.expr(e, callable)
|
||||
val c: IrClass = e.symbol.owner
|
||||
val instance = useObjectClassInstance(c)
|
||||
|
||||
val id = tw.getFreshIdLabel<DbVaraccess>()
|
||||
val type = useType(e.type)
|
||||
val locId = tw.getLocation(e)
|
||||
tw.writeExprs_varaccess(id, type.javaResult.id, type.kotlinResult.id, exprParent.parent, exprParent.idx)
|
||||
tw.writeHasLocation(id, locId)
|
||||
|
||||
tw.writeVariableBinding(id, instance.id)
|
||||
}
|
||||
else -> {
|
||||
logger.warnElement(Severity.ErrorSevere, "Unrecognised IrExpression: " + e.javaClass, e)
|
||||
}
|
||||
|
||||
@@ -314,6 +314,11 @@ classes(
|
||||
int sourceid: @class ref
|
||||
);
|
||||
|
||||
class_object(
|
||||
unique int id: @class ref,
|
||||
unique int instance: @field ref
|
||||
);
|
||||
|
||||
kt_nullable_types(
|
||||
unique int id: @kt_nullable_type,
|
||||
int classid: @classorinterface ref
|
||||
|
||||
@@ -712,6 +712,18 @@ class Class extends ClassOrInterface, @class {
|
||||
override string getAPrimaryQlClass() { result = "Class" }
|
||||
}
|
||||
|
||||
/** A Kotlin `object`. */
|
||||
class ClassObject extends Class {
|
||||
ClassObject() {
|
||||
class_object(this, _)
|
||||
}
|
||||
|
||||
/** Gets the instance variable that implements this `object`. */
|
||||
Field getInstance() {
|
||||
class_object(this, result)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A record declaration.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| objects.kt:2:1:4:1 | MyObject | objects.kt:7:17:7:24 | INSTANCE |
|
||||
8
java/ql/test/kotlin/library-tests/object/accesses.ql
Normal file
8
java/ql/test/kotlin/library-tests/object/accesses.ql
Normal file
@@ -0,0 +1,8 @@
|
||||
import java
|
||||
|
||||
from VarAccess va, ClassObject co
|
||||
where va.getVariable() = co.getInstance()
|
||||
select co, va
|
||||
|
||||
// select count(VarAccess va)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| objects.kt:2:1:4:1 | MyObject | objects.kt:2:1:4:1 | INSTANCE |
|
||||
9
java/ql/test/kotlin/library-tests/object/objects.kt
Normal file
9
java/ql/test/kotlin/library-tests/object/objects.kt
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
object MyObject {
|
||||
fun MyObjectFunction() {}
|
||||
}
|
||||
|
||||
fun useMyObject() {
|
||||
val myObj = MyObject
|
||||
}
|
||||
|
||||
5
java/ql/test/kotlin/library-tests/object/objects.ql
Normal file
5
java/ql/test/kotlin/library-tests/object/objects.ql
Normal file
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from ClassObject co
|
||||
where co.fromSource()
|
||||
select co, co.getInstance()
|
||||
Reference in New Issue
Block a user