Repository: joernio/joern (scala)

Issue:
[GO] Handle global variable and constant
Global variable and constant is declared here: https://github.com/apm-dev/go-user-rest-api/blob/main/datasources/mysql/users_db/users_db.go

global variable is used here: https://github.com/apm-dev/go-user-rest-api/blob/main/domain/users/user_dao.go
(stmt, err := users_db.Client.Prepare(queryGetAll))

End outcome to verify: MethodFullName property for below call nodes would be get resolved:

cpg.call("Prepare").l

Pull request:
Prerequisite changes to fix #3695 issue.

Handling done to set the member node under given TypeDecl parent.

Patch:
diff --git a/build.sbt b/build.sbt
index bdb22e58ab04..8efa6ea389c2 100644
--- a/build.sbt
+++ b/build.sbt
@@ -2,7 +2,7 @@ name                     := "joern"
 ThisBuild / organization := "io.joern"
 ThisBuild / scalaVersion := "3.3.1"
 
-val cpgVersion = "1.4.23"
+val cpgVersion = "1.4.24"
 
 lazy val joerncli          = Projects.joerncli
 lazy val querydb           = Projects.querydb
@@ -64,7 +64,7 @@ ThisBuild / compile / javacOptions ++= Seq(
 ThisBuild / scalacOptions ++= Seq(
   "-deprecation", // Emit warning and location for usages of deprecated APIs.
   "--release",
-  "11",
+  "11"
 )
 
 lazy val createDistribution = taskKey[File]("Create a complete Joern distribution")
diff --git a/joern-cli/frontends/x2cpg/src/main/scala/io/joern/x2cpg/passes/base/AstLinkerPass.scala b/joern-cli/frontends/x2cpg/src/main/scala/io/joern/x2cpg/passes/base/AstLinkerPass.scala
index db1d38197239..5fd666d2fa43 100644
--- a/joern-cli/frontends/x2cpg/src/main/scala/io/joern/x2cpg/passes/base/AstLinkerPass.scala
+++ b/joern-cli/frontends/x2cpg/src/main/scala/io/joern/x2cpg/passes/base/AstLinkerPass.scala
@@ -5,7 +5,7 @@ import io.shiftleft.codepropertygraph.Cpg
 import io.shiftleft.codepropertygraph.generated.nodes.StoredNode
 import io.shiftleft.codepropertygraph.generated.{EdgeTypes, NodeTypes}
 import io.shiftleft.passes.CpgPass
-import io.shiftleft.semanticcpg.language._
+import io.shiftleft.semanticcpg.language.*
 
 class AstLinkerPass(cpg: Cpg) extends CpgPass(cpg) with LinkingUtil {
 
@@ -16,6 +16,15 @@ class AstLinkerPass(cpg: Cpg) extends CpgPass(cpg) with LinkingUtil {
     cpg.typeDecl.whereNot(_.astParent).foreach { typeDecl =>
       addAstParent(typeDecl, typeDecl.fullName, typeDecl.astParentType, typeDecl.astParentFullName, dstGraph)
     }
+    cpg.member.whereNot(_.astParent).foreach { member =>
+      addAstParent(
+        member,
+        s"${member.astParentFullName}.${member.name}",
+        member.astParentType,
+        member.astParentFullName,
+        dstGraph
+      )
+    }
   }
 
   /** For the given method or type declaration, determine its parent in the AST via the AST_PARENT_TYPE and


Test patch:
diff --git a/joern-cli/frontends/x2cpg/src/test/scala/io/joern/x2cpg/passes/AstLinkerPassTest.scala b/joern-cli/frontends/x2cpg/src/test/scala/io/joern/x2cpg/passes/AstLinkerPassTest.scala
new file mode 100644
index 000000000000..148b5e9c224f
--- /dev/null
+++ b/joern-cli/frontends/x2cpg/src/test/scala/io/joern/x2cpg/passes/AstLinkerPassTest.scala
@@ -0,0 +1,36 @@
+package io.joern.x2cpg.passes
+
+import io.joern.x2cpg.layers.Base
+import io.joern.x2cpg.passes.base.AstLinkerPass
+import io.joern.x2cpg.{Ast, ValidationMode}
+import io.shiftleft.codepropertygraph.generated.*
+import io.shiftleft.codepropertygraph.generated.nodes.{NewCall, NewMember, NewTypeDecl}
+import io.shiftleft.semanticcpg.language.*
+import io.shiftleft.semanticcpg.layers.LayerCreatorContext
+import io.shiftleft.semanticcpg.testing.MockCpg
+import org.scalatest.matchers.should.Matchers
+import org.scalatest.wordspec.AnyWordSpec
+
+class AstLinkerPassTest extends AnyWordSpec with Matchers {
+
+  "Check member node is child of TypeDecl node" in {
+    val cpg = MockCpg().withCustom { (graph, _) =>
+      implicit val withSchemaValidation: ValidationMode = ValidationMode.Disabled
+      val typeDecl                                      = NewTypeDecl().name("Sample").fullName("namespace.Sample")
+      Ast.storeInDiffGraph(Ast(typeDecl), graph)
+      val memberNode = NewMember()
+        .name("test")
+        .typeFullName("String")
+        .astParentType(NodeTypes.TYPE_DECL)
+        .astParentFullName("namespace.Sample")
+      Ast.storeInDiffGraph(Ast(memberNode), graph)
+    }.cpg
+
+    val context = new LayerCreatorContext(cpg)
+    new Base().run(context)
+    val List(typeDecl) = cpg.typeDecl("Sample").l
+    val List(member)   = typeDecl.member.l
+    member.typeFullName shouldBe "String"
+    member.name shouldBe "test"
+  }
+}