Skip to content

Commit c3bd8b7

Browse files
TNSelahleTebogo Selahle
andauthored
[kotlin2cpg] Structured ClosureBindingId (#5682)
* feat: improve closureBindingId value * fix: include node name in closureBindingId * fix: resolve test --------- Co-authored-by: Tebogo Selahle <[email protected]>
1 parent de6cfa2 commit c3bd8b7

File tree

3 files changed

+36
-16
lines changed

3 files changed

+36
-16
lines changed

joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstCreator.scala

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,10 +212,6 @@ class AstCreator(
212212
}
213213
}
214214

215-
protected def stringForUUID(node: KtExpression, name: String, typeFullName: String): String = {
216-
node.getText + node.getContainingKtFile.getName + node.getContainingKtFile.getPackageFqName.toString + name + typeFullName
217-
}
218-
219215
protected def ktTokenToOperator(forPostfixExpr: Boolean): PartialFunction[KtToken, String] = {
220216
val postfixKtTokenToOperator: PartialFunction[KtToken, String] = {
221217
case KtTokens.EXCLEXCL => Operators.notNullAssert

joern-cli/frontends/kotlin2cpg/src/main/scala/io/joern/kotlin2cpg/ast/AstForFunctionsCreator.scala

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.resolve.sam.SamConstructorDescriptor
2626
import org.jetbrains.kotlin.resolve.sam.SamConversionResolverImplKt
2727
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
2828

29-
import java.util.UUID.nameUUIDFromBytes
3029
import scala.collection.mutable
3130
import scala.jdk.CollectionConverters.*
3231

@@ -294,8 +293,7 @@ trait AstForFunctionsCreator(implicit withSchemaValidation: ValidationMode) {
294293
case node: NewLocal => NodeContext(node, node.name, node.typeFullName)
295294
}
296295
.map { capturedNodeContext =>
297-
val uuidBytes = stringForUUID(fn, capturedNodeContext.name, capturedNodeContext.typeFullName)
298-
val closureBindingId = nameUUIDFromBytes(uuidBytes.getBytes).toString
296+
val closureBindingId = s"$descFullName.${capturedNodeContext.name}"
299297
val closureBinding = closureBindingNode(closureBindingId, EvaluationStrategies.BY_REFERENCE)
300298
(closureBinding, capturedNodeContext)
301299
}
@@ -397,8 +395,7 @@ trait AstForFunctionsCreator(implicit withSchemaValidation: ValidationMode) {
397395
case node: NewLocal => NodeContext(node, node.name, node.typeFullName)
398396
}
399397
.map { capturedNodeContext =>
400-
val uuidBytes = stringForUUID(expr, capturedNodeContext.name, capturedNodeContext.typeFullName)
401-
val closureBindingId = nameUUIDFromBytes(uuidBytes.getBytes).toString
398+
val closureBindingId = s"$descFullName.${capturedNodeContext.name}"
402399
val closureBinding = closureBindingNode(closureBindingId, EvaluationStrategies.BY_REFERENCE)
403400
(closureBinding, capturedNodeContext)
404401
}

joern-cli/frontends/kotlin2cpg/src/test/scala/io/joern/kotlin2cpg/querying/LambdaTests.scala

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class LambdaTests extends KotlinCode2CpgFixture(withOssDataflow = false, withDef
2525
"should contain a CLOSURE_BINDING node for the captured parameter with the correct props set" in {
2626
val List(cb) = cpg.closureBinding.l
2727
cb.evaluationStrategy shouldBe EvaluationStrategies.BY_REFERENCE
28-
cb.closureBindingId should not be None
28+
cb.closureBindingId shouldBe Some("f1.<lambda>0.p")
2929

3030
cb._refOut.size shouldBe 1
3131
cb._methodParameterInViaRefOut.get.name shouldBe "p"
@@ -45,9 +45,12 @@ class LambdaTests extends KotlinCode2CpgFixture(withOssDataflow = false, withDef
4545

4646
"CPG for code with a simple lambda which captures a local" should {
4747
val cpg = code("""
48-
|fun foo(x: String) {
49-
| val baz: String = "BAZ"
50-
| 1.let { println(baz) }
48+
|package simple.pkg
49+
|class Bar {
50+
| fun foo(x: String) {
51+
| val baz: String = "BAZ"
52+
| 1.let { println(baz) }
53+
| }
5154
|}
5255
|""".stripMargin)
5356

@@ -57,8 +60,16 @@ class LambdaTests extends KotlinCode2CpgFixture(withOssDataflow = false, withDef
5760
mr.code should not be null
5861
}
5962

60-
"should contain two CAPTURE edges for the METHOD_REF" in {
61-
cpg.methodRef.outE.collectAll[Capture].size shouldBe 2
63+
"should contain three CAPTURE edges for the METHOD_REF" in {
64+
cpg.methodRef.outE.collectAll[Capture].size shouldBe 3
65+
}
66+
67+
"should contain a LOCAL node for the captured `this`" in {
68+
cpg.local.code("this").size shouldBe 1
69+
}
70+
71+
"should contain a LOCAL node for the captured `x`" in {
72+
cpg.local.code("x").size shouldBe 1
6273
}
6374

6475
"should contain a LOCAL node for the captured `baz`" in {
@@ -68,7 +79,23 @@ class LambdaTests extends KotlinCode2CpgFixture(withOssDataflow = false, withDef
6879
"should contain a CLOSURE_BINDING node for captured `baz` with the correct props set" in {
6980
val List(cb) = cpg.closureBinding.filter(_._localViaRefOut.name.l == List("baz")).l
7081
cb.evaluationStrategy shouldBe EvaluationStrategies.BY_REFERENCE
71-
cb.closureBindingId should not be None
82+
cb.closureBindingId shouldBe Some("simple.pkg.Bar.foo.<lambda>0.baz")
83+
84+
cb._refOut.size shouldBe 1
85+
}
86+
87+
"should contain a CLOSURE_BINDING node for captured `x` with the correct props set" in {
88+
val List(cb) = cpg.closureBinding.filter(_._methodParameterInViaRefOut.name.l == List("x")).l
89+
cb.evaluationStrategy shouldBe EvaluationStrategies.BY_REFERENCE
90+
cb.closureBindingId shouldBe Some("simple.pkg.Bar.foo.<lambda>0.x")
91+
92+
cb._refOut.size shouldBe 1
93+
}
94+
95+
"should contain a CLOSURE_BINDING node for captured `this` with the correct props set" in {
96+
val List(cb) = cpg.closureBinding.filter(_._methodParameterInViaRefOut.name.l == List("this")).l
97+
cb.evaluationStrategy shouldBe EvaluationStrategies.BY_REFERENCE
98+
cb.closureBindingId shouldBe Some("simple.pkg.Bar.foo.<lambda>0.this")
7299

73100
cb._refOut.size shouldBe 1
74101
}

0 commit comments

Comments
 (0)