Repository: joernio/joern (scala)

Issue:
[Bug] Vue attributes loose leading colon
see https://github.com/joernio/joern/blob/de0f3877c5b00be7cd3d4548cc562d88e2ff5c6a/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/passes/ast/VueJsDomAstCreationPassTest.scala#L13-L20

Pull request description:
Fixes: https://github.com/joernio/joern/issues/2399

Patch:
diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForTemplateDomCreator.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForTemplateDomCreator.scala
index 7650ce584c2a..dcaf3680ee76 100644
--- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForTemplateDomCreator.scala
+++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForTemplateDomCreator.scala
@@ -36,7 +36,22 @@ trait AstForTemplateDomCreator { this: AstCreator =>
   }
 
   protected def astForJsxAttribute(jsxAttr: BabelNodeInfo): Ast = {
-    val domNode = createTemplateDomNode(jsxAttr.node.toString, jsxAttr.code, jsxAttr.lineNumber, jsxAttr.columnNumber)
+    // A colon in front of a JSXAttribute cant be parsed by Babel.
+    // Hence, we strip it away with astgen and restore it here.
+    // parserResult.fileContent contains the unmodified Vue.js source code for the current file.
+    // We look at the previous character there and re-add the colon if needed.
+    val colon = pos(jsxAttr.json)
+      .collect {
+        case position if position > 0 && parserResult.fileContent.substring(position - 1, position) == ":" => ":"
+      }
+      .getOrElse("")
+    val domNode =
+      createTemplateDomNode(
+        jsxAttr.node.toString,
+        s"$colon${jsxAttr.code}",
+        jsxAttr.lineNumber,
+        jsxAttr.columnNumber.map(_ - colon.length)
+      )
     val valueAst = safeObj(jsxAttr.json, "value")
       .map(e => astForNodeWithFunctionReference(Obj(e)))
       .getOrElse(Ast())


Test patch:
diff --git a/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/passes/ast/VueJsDomAstCreationPassTest.scala b/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/passes/ast/VueJsDomAstCreationPassTest.scala
index 8df1a460b8ee..a39cf976bfdb 100644
--- a/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/passes/ast/VueJsDomAstCreationPassTest.scala
+++ b/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/passes/ast/VueJsDomAstCreationPassTest.scala
@@ -17,8 +17,8 @@ class VueJsDomAstCreationPassTest extends AbstractDomPassTest {
       cpg.file.name.l shouldBe List("test.vue")
       cpg.templateDom.nameExact("JSXAttribute").code.l shouldBe List(
         "v-for=\"image in images\"",
-        "src=\"image.url\"",
-        "attr=\"image.name\"",
+        ":src=\"image.url\"",
+        ":attr=\"image.name\"",
         "v-bind:alt=\"image.description\""
       )
       templateDomName(cpg) shouldBe Set(