Skip to content

Commit

Permalink
[swiftsrc2cpg] Initial work to get file content going (#4169)
Browse files Browse the repository at this point in the history
  • Loading branch information
max-leuthaeuser authored Feb 14, 2024
1 parent 4777e41 commit 33ddb87
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import io.shiftleft.codepropertygraph.generated.nodes.NewNode
import io.shiftleft.codepropertygraph.generated.nodes.NewTypeDecl
import io.shiftleft.codepropertygraph.generated.nodes.NewTypeRef
import io.shiftleft.codepropertygraph.generated.ModifierTypes
import io.shiftleft.codepropertygraph.generated.nodes.File.PropertyDefaults
import org.slf4j.{Logger, LoggerFactory}
import overflowdb.BatchedUpdate.DiffGraphBuilder

Expand Down Expand Up @@ -62,7 +63,9 @@ class AstCreator(val config: Config, val global: SwiftGlobal, val parserResult:
}

override def createAst(): DiffGraphBuilder = {
val fileNode = NewFile().name(parserResult.filename).order(1)
val fileContent = if (!config.disableFileContent) Option(parserResult.fileContent) else None
val fileNode = NewFile().name(parserResult.filename).order(1)
fileContent.foreach(fileNode.content(_))
val namespaceBlock = globalNamespaceBlock()
methodAstParentStack.push(namespaceBlock)
val astForFakeMethod =
Expand Down Expand Up @@ -127,13 +130,28 @@ class AstCreator(val config: Config, val global: SwiftGlobal, val parserResult:
case null => notHandledYet(node)
}

protected def line(node: SwiftNode): Option[Integer] = node.startLine.map(Integer.valueOf)
protected def column(node: SwiftNode): Option[Integer] = node.startColumn.map(Integer.valueOf)
protected def lineEnd(node: SwiftNode): Option[Integer] = node.endLine.map(Integer.valueOf)
protected def columnEnd(node: SwiftNode): Option[Integer] = node.endColumn.map(Integer.valueOf)
protected def code(node: SwiftNode): String = {
val startIndex = Math.min(node.startOffset.getOrElse(0), parserResult.fileContent.length)
val endIndex = Math.min(node.endOffset.getOrElse(0), parserResult.fileContent.length)
shortenCode(parserResult.fileContent.substring(startIndex, endIndex).trim)
override protected def line(node: SwiftNode): Option[Integer] = node.startLine.map(Integer.valueOf)
override protected def column(node: SwiftNode): Option[Integer] = node.startColumn.map(Integer.valueOf)
override protected def lineEnd(node: SwiftNode): Option[Integer] = node.endLine.map(Integer.valueOf)
override protected def columnEnd(node: SwiftNode): Option[Integer] = node.endColumn.map(Integer.valueOf)

private def nodeOffsets(node: SwiftNode): Option[(Int, Int)] = {
for {
startOffset <- node.startOffset
endOffset <- node.endOffset
} yield (startOffset, endOffset)
}

override protected def offset(node: SwiftNode): Option[(Int, Int)] = {
Option.when(!config.disableFileContent) { nodeOffsets(node) }.flatten
}

override protected def code(node: SwiftNode): String = {
nodeOffsets(node) match {
case Some((startOffset, endOffset))
if startOffset < endOffset && startOffset >= 0 && endOffset <= parserResult.fileContent.length =>
shortenCode(parserResult.fileContent.substring(startOffset, endOffset).trim)
case _ => PropertyDefaults.Code
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.joern.swiftsrc2cpg.io

import io.joern.swiftsrc2cpg.testfixtures.SwiftSrc2CpgSuite
import io.joern.swiftsrc2cpg.Config
import io.shiftleft.semanticcpg.language.*

class CodeDumperFromContentTest extends SwiftSrc2CpgSuite {

private val codeString = """
|// A comment
|func my_func(param1: Int) -> Int {
| let x: Int = foo(p: param1)
|}""".stripMargin

"dumping code from content" should {
implicit val finder: NodeExtensionFinder = DefaultNodeExtensionFinder

val cpg = code(codeString, "test.swift").withConfig(Config().withDisableFileContent(false))

"allow one to dump a method node's source code from `File.contents`" in {
inside(cpg.method.nameExact("my_func").dumpRaw.l) {
case content :: Nil =>
content.linesIterator.map(_.strip).l shouldBe List(
"func my_func(param1: Int) -> Int { /* <=== test.swift:<global>:my_func */",
"let x: Int = foo(p: param1)",
"}"
)
case content => fail(s"Expected exactly 1 content dump, but got: $content")
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import io.shiftleft.semanticcpg.language._

import java.util.regex.Pattern

class CodeDumperTest extends SwiftSrc2CpgSuite {
class CodeDumperFromFileTest extends SwiftSrc2CpgSuite {

implicit val finder: NodeExtensionFinder = DefaultNodeExtensionFinder

Expand All @@ -34,7 +34,7 @@ class CodeDumperTest extends SwiftSrc2CpgSuite {
path.delete(swallowIOExceptions = true)
}

"dumping code" should {
"dumping code from file" should {

"return empty string for empty traversal" in {
cpg.method.name("notinthere").dump shouldBe empty
Expand Down Expand Up @@ -68,6 +68,7 @@ class CodeDumperTest extends SwiftSrc2CpgSuite {
val code = cpg.method.name("foo").callIn.dumpRaw.mkString("\n")
code should startWith("func my_func")
}

}

}

0 comments on commit 33ddb87

Please sign in to comment.