Skip to content

Commit

Permalink
Set code field for all methods (#115)
Browse files Browse the repository at this point in the history
Capped with number of chars: 50 >= code field length <= 1000 (multiple whitespace and newlines are replaced)
This gives a nice overview for methods (especially for anonymous functions) when debugging / traversing the CPG.
  • Loading branch information
max-leuthaeuser authored Jan 25, 2022
1 parent e9b7114 commit b5693d9
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,7 @@ class AstCreator(diffGraph: DiffGraph.Builder, source: JsSource, usedIdentNodes:

val (methodName, methodFullName) = calcMethodNameAndFullName(functionNode)

val methodId = astNodeBuilder.createMethodNode(methodName,
methodFullName,
astNodeBuilder.lineAndColumn(functionNode))
val methodId = astNodeBuilder.createMethodNode(methodName, methodFullName, functionNode)
addMethodToAst(methodId)

if (!functionNode.isProgram) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import io.shiftleft.js2cpg.cpg.datastructures.{LineAndColumn, OrderTracker}
import io.shiftleft.js2cpg.cpg.datastructures.scope.{MethodScope, Scope}
import io.shiftleft.js2cpg.cpg.passes.Defines
import io.shiftleft.js2cpg.parser.JsSource
import io.shiftleft.js2cpg.parser.JsSource.shortenCode
import io.shiftleft.passes.DiffGraph
import org.apache.commons.lang.StringUtils

class AstNodeBuilder[NodeBuilderType](private val diffGraph: DiffGraph.Builder,
private val astEdgeBuilder: AstEdgeBuilder,
Expand All @@ -23,10 +23,6 @@ class AstNodeBuilder[NodeBuilderType](private val diffGraph: DiffGraph.Builder,
case _ => ""
}

private val MAX_CODE_LENGTH: Int = 1000

private def shortenCode(code: String): String = StringUtils.abbreviate(code, MAX_CODE_LENGTH)

def lineAndColumn(node: Node): LineAndColumn = {
LineAndColumn(source.getLine(node), source.getColumn(node))
}
Expand Down Expand Up @@ -366,16 +362,16 @@ class AstNodeBuilder[NodeBuilderType](private val diffGraph: DiffGraph.Builder,

def createMethodNode(methodName: String,
methodFullName: String,
lineAndColumn: LineAndColumn): NewMethod = {
val line = lineAndColumn.line
val column = lineAndColumn.column
// TODO: we might want to fix this later:
val code = methodFullName
functionNode: FunctionNode): NewMethod = {
val lineColumn = lineAndColumn(functionNode)
val line = lineColumn.line
val column = lineColumn.column
val code = shortenCode(sanitizeCode(functionNode))

val method = NewMethod()
.name(methodName)
.filename(source.filePath)
.code(shortenCode(code))
.code(code)
.fullName(methodFullName)
.isExternal(false)
.lineNumber(line)
Expand Down
21 changes: 16 additions & 5 deletions src/main/scala/io/shiftleft/js2cpg/parser/JsSource.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,36 @@ import com.oracle.js.parser.ir.Node
import io.shiftleft.js2cpg.io.FileDefaults._
import io.shiftleft.js2cpg.io.FileUtils
import io.shiftleft.js2cpg.preprocessing.NuxtTranspiler
import org.apache.commons.lang.StringUtils
import org.slf4j.LoggerFactory

import scala.jdk.CollectionConverters._
import scala.util.{Failure, Success, Try}

class JsSource(val srcDir: File, val projectDir: Path, val source: Source) {
object JsSource {

private val logger = LoggerFactory.getLogger(getClass)

// maximum length of re-mapped code fields after transpilation in number of characters
val MAX_CODE_LENGTH: Int = 1000
val MIN_CODE_LENGTH: Int = 50

def shortenCode(code: String, length: Int = MAX_CODE_LENGTH): String =
StringUtils.abbreviate(StringUtils.normalizeSpace(code), math.max(MIN_CODE_LENGTH, length))

}

class JsSource(val srcDir: File, val projectDir: Path, val source: Source) {

import JsSource._

private val absoluteFilePath = (File(projectDir.toAbsolutePath) / originalFilePath).pathAsString
private val mapFilePath = absoluteFilePath + ".map"
private val sourceMap = sourceMapOrigin()

private val (positionToLineNumberMapping, positionToFirstPositionInLineMapping) =
FileUtils.positionLookupTables(source.getString)

// maximum length of re-mapped code fields after transpilation in number of characters
private val MAX_CODE_LENGTH = 100

private case class SourceMapOrigin(sourceFilePath: Path,
sourceMap: Option[ReadableSourceMap],
sourceWithLineNumbers: Map[Int, String])
Expand Down Expand Up @@ -202,7 +213,7 @@ class JsSource(val srcDir: File, val projectDir: Path, val source: Source) {
transpiledCodeLength: Int): String =
currentLine match {
case line if line.length >= transpiledCodeLength =>
line.substring(0, transpiledCodeLength - 1).stripLineEnd + " [...]"
shortenCode(line, transpiledCodeLength - 1)
case line
if line.length < transpiledCodeLength && sourceWithLineNumbers.contains(
currentLineNumber + 1) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import io.shiftleft.js2cpg.core.Js2CpgMain
import io.shiftleft.semanticcpg.language.toMethodForCallGraph
import io.shiftleft.semanticcpg.language.toNodeTypeStarters
import io.shiftleft.semanticcpg.language.NoResolve
import io.shiftleft.semanticcpg.language.toCfgNodeMethods
import io.shiftleft.semanticcpg.language.toTraversal
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
import org.scalatest.Inside
Expand Down Expand Up @@ -41,7 +39,6 @@ class CallLinkerPassTest extends AnyWordSpec with Matchers with Inside {
inside(cpg.method("sayhi").l) {
case List(m) =>
m.name shouldBe "sayhi"
m.code should endWith(".js::program:sayhi")
m.fullName should endWith(".js::program:sayhi")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ class CfgCreationPassTest extends AnyWordSpec with Matchers {
succOf("2") shouldBe expected(("_tmp_0.key2 = 2", AlwaysEdge))

succOf("_tmp_0.key2 = 2") shouldBe expected(("_tmp_0", 2, AlwaysEdge))
succOf("_tmp_0", 2) shouldBe expected(("x = {\n key1: \"value\",\n key2: 2\n}", AlwaysEdge))
succOf("x = {\n key1: \"value\",\n key2: 2\n}") shouldBe expected(("RET", AlwaysEdge))
succOf("_tmp_0", 2) shouldBe expected(("x = { key1: \"value\", key2: 2 }", AlwaysEdge))
succOf("x = { key1: \"value\", key2: 2 }") shouldBe expected(("RET", AlwaysEdge))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,18 @@ class TranspilationRunnerTest extends AnyWordSpec with Matchers {
Config.withDefaults.withStorageLocation(cpgPath)))
fileNames(cpg) should contain theSameElementsAs List("foo.js")
codeFields(cpg) should contain allElementsOf List(
"__ecma.Array.factory()",
"_tmp_1 = __ecma.Array.factory()",
"_tmp_1.push(1)",
"_tmp_1.push",
"_tmp_1.push(2)",
"_tmp_1.push",
"_tmp_1.push(3)",
"(_tmp_0 = [1, 2, 3 [...])",
"(_tmp_0 = [1, 2, 3 [...]).map",
"_tmp_1.push",
"(_tmp_0 = [1, 2, 3].map((n) => n + 1);)",
"(_tmp_0 = [1, 2, 3].map((n) => n + 1);).map",
"n + 1",
"[1, 2, 3 [...].map(anonymous)"
"[1, 2, 3].map((n) => n + 1);.map(anonymous)"
)
}

Expand Down

0 comments on commit b5693d9

Please sign in to comment.