Skip to content

Commit

Permalink
[jssrc2cpg] Overhaul typedecl method bindings (#4727)
Browse files Browse the repository at this point in the history
  • Loading branch information
max-leuthaeuser authored Jul 5, 2024
1 parent 0c49cb9 commit cf8d139
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 367 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ trait AstForExpressionsCreator(implicit withSchemaValidation: ValidationMode) {
case MemberExpression => code(callee.json("property"))
case _ => callee.code
}
val callNode =
createStaticCallNode(callExpr.code, callName, fullName, callee.lineNumber, callee.columnNumber)
val argAsts = astForNodes(callExpr.json("arguments").arr.toList)
val callNode = createStaticCallNode(callExpr.code, callName, fullName, callee.lineNumber, callee.columnNumber)
val argAsts = astForNodes(callExpr.json("arguments").arr.toList)
callAst(callNode, argAsts)
}

Expand Down Expand Up @@ -114,9 +113,7 @@ trait AstForExpressionsCreator(implicit withSchemaValidation: ValidationMode) {
diffGraph.addEdge(localAstParentStack.head, localTmpAllocNode, EdgeTypes.AST)
scope.addVariableReference(tmpAllocName, tmpAllocNode1)

val allocCallNode =
callNode(newExpr, ".alloc", Operators.alloc, DispatchTypes.STATIC_DISPATCH)

val allocCallNode = callNode(newExpr, ".alloc", Operators.alloc, DispatchTypes.STATIC_DISPATCH)
val assignmentTmpAllocCallNode =
createAssignmentCallAst(
tmpAllocNode1,
Expand All @@ -126,12 +123,9 @@ trait AstForExpressionsCreator(implicit withSchemaValidation: ValidationMode) {
newExpr.columnNumber
)

val tmpAllocNode2 = identifierNode(newExpr, tmpAllocName)

val receiverNode = astForNodeWithFunctionReference(callee)

val callAst = handleCallNodeArgs(newExpr, receiverNode, tmpAllocNode2, Defines.OperatorsNew)

val tmpAllocNode2 = identifierNode(newExpr, tmpAllocName)
val receiverNode = astForNodeWithFunctionReference(callee)
val callAst = handleCallNodeArgs(newExpr, receiverNode, tmpAllocNode2, Defines.OperatorsNew)
val tmpAllocReturnNode = Ast(identifierNode(newExpr, tmpAllocName))

scope.popScope()
Expand Down Expand Up @@ -217,31 +211,21 @@ trait AstForExpressionsCreator(implicit withSchemaValidation: ValidationMode) {
astForBinaryExpression(logicalExpr)

protected def astForTSNonNullExpression(nonNullExpr: BabelNodeInfo): Ast = {
val op = Operators.notNullAssert
val callNode_ =
callNode(nonNullExpr, nonNullExpr.code, op, DispatchTypes.STATIC_DISPATCH)
val argAsts = List(astForNodeWithFunctionReference(nonNullExpr.json("expression")))
val op = Operators.notNullAssert
val callNode_ = callNode(nonNullExpr, nonNullExpr.code, op, DispatchTypes.STATIC_DISPATCH)
val argAsts = List(astForNodeWithFunctionReference(nonNullExpr.json("expression")))
callAst(callNode_, argAsts)
}

protected def astForCastExpression(castExpr: BabelNodeInfo): Ast = {
val op = Operators.cast
val lhsNode = castExpr.json("typeAnnotation")
val rhsAst = astForNodeWithFunctionReference(castExpr.json("expression"))
typeFor(castExpr) match {
case tpe if GlobalBuiltins.builtins.contains(tpe) || Defines.isBuiltinType(tpe) =>
val lhsAst = Ast(literalNode(castExpr, code(lhsNode), Option(tpe)))
val node =
callNode(castExpr, castExpr.code, op, DispatchTypes.STATIC_DISPATCH).dynamicTypeHintFullName(Seq(tpe))
val argAsts = List(lhsAst, rhsAst)
callAst(node, argAsts)
case t =>
val possibleTypes = Seq(t)
val lhsAst = Ast(literalNode(castExpr, code(lhsNode), None).possibleTypes(possibleTypes))
val node = callNode(castExpr, castExpr.code, op, DispatchTypes.STATIC_DISPATCH).possibleTypes(possibleTypes)
val argAsts = List(lhsAst, rhsAst)
callAst(node, argAsts)
}
val op = Operators.cast
val lhsNode = castExpr.json("typeAnnotation")
val rhsAst = astForNodeWithFunctionReference(castExpr.json("expression"))
val possibleTypes = Seq(typeFor(castExpr))
val lhsAst = Ast(literalNode(castExpr, code(lhsNode), None).possibleTypes(possibleTypes))
val node = callNode(castExpr, castExpr.code, op, DispatchTypes.STATIC_DISPATCH).possibleTypes(possibleTypes)
val argAsts = List(lhsAst, rhsAst)
callAst(node, argAsts)
}

protected def astForBinaryExpression(binExpr: BabelNodeInfo): Ast = {
Expand Down Expand Up @@ -340,8 +324,7 @@ trait AstForExpressionsCreator(implicit withSchemaValidation: ValidationMode) {
}

protected def astForAwaitExpression(awaitExpr: BabelNodeInfo): Ast = {
val node =
callNode(awaitExpr, awaitExpr.code, "<operator>.await", DispatchTypes.STATIC_DISPATCH)
val node = callNode(awaitExpr, awaitExpr.code, "<operator>.await", DispatchTypes.STATIC_DISPATCH)
val argAsts = List(astForNodeWithFunctionReference(awaitExpr.json("argument")))
callAst(node, argAsts)
}
Expand Down Expand Up @@ -417,12 +400,11 @@ trait AstForExpressionsCreator(implicit withSchemaValidation: ValidationMode) {
}

def astForTemplateExpression(templateExpr: BabelNodeInfo): Ast = {
val argumentAst = astForNodeWithFunctionReference(templateExpr.json("quasi"))
val callName = code(templateExpr.json("tag"))
val callCode = s"$callName(${codeOf(argumentAst.nodes.head)})"
val templateExprCall =
callNode(templateExpr, callCode, callName, DispatchTypes.STATIC_DISPATCH)
val argAsts = List(argumentAst)
val argumentAst = astForNodeWithFunctionReference(templateExpr.json("quasi"))
val callName = code(templateExpr.json("tag"))
val callCode = s"$callName(${codeOf(argumentAst.nodes.head)})"
val templateExprCall = callNode(templateExpr, callCode, callName, DispatchTypes.STATIC_DISPATCH)
val argAsts = List(argumentAst)
callAst(templateExprCall, argAsts)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import io.joern.jssrc2cpg.parser.BabelAst.*
import io.joern.jssrc2cpg.parser.BabelNodeInfo
import io.joern.x2cpg.datastructures.Stack.*
import io.joern.x2cpg.frontendspecific.jssrc2cpg.Defines
import io.joern.x2cpg.utils.NodeBuilders.{newBindingNode, newModifierNode}
import io.joern.x2cpg.utils.NodeBuilders.newModifierNode
import io.joern.x2cpg.{Ast, ValidationMode}
import io.shiftleft.codepropertygraph.generated.nodes.{Identifier as _, *}
import io.shiftleft.codepropertygraph.generated.{DispatchTypes, EdgeTypes, EvaluationStrategies, ModifierTypes}
Expand Down Expand Up @@ -325,10 +325,13 @@ trait AstForFunctionsCreator(implicit withSchemaValidation: ValidationMode) { th
}

protected def astForTSDeclareFunction(func: BabelNodeInfo): Ast = {
val functionNode = createMethodDefinitionNode(func)
val bindingNode = newBindingNode("", "", "")
diffGraph.addEdge(getParentTypeDecl, bindingNode, EdgeTypes.BINDS)
diffGraph.addEdge(bindingNode, functionNode, EdgeTypes.REF)
val functionNode = createMethodDefinitionNode(func)
val tpe = typeFor(func)
val possibleTypes = Seq(tpe)
val typeFullName = if (Defines.isBuiltinType(tpe)) tpe else Defines.Any
val memberNode_ = memberNode(func, functionNode.name, func.code, typeFullName, Seq(functionNode.fullName))
.possibleTypes(possibleTypes)
diffGraph.addEdge(getParentTypeDecl, memberNode_, EdgeTypes.AST)
addModifier(functionNode, func.json)
Ast(functionNode)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import io.joern.jssrc2cpg.parser.BabelNodeInfo
import io.joern.x2cpg.{Ast, ValidationMode}
import io.joern.x2cpg.datastructures.Stack.*
import io.joern.x2cpg.frontendspecific.jssrc2cpg.Defines
import io.joern.x2cpg.utils.NodeBuilders.newBindingNode
import io.shiftleft.codepropertygraph.generated.nodes.*
import io.shiftleft.codepropertygraph.generated.{DispatchTypes, EdgeTypes, ModifierTypes, Operators}
import ujson.Value
Expand Down Expand Up @@ -180,18 +179,12 @@ trait AstForTypesCreator(implicit withSchemaValidation: ValidationMode) { this:
val typeFullName = if (Defines.isBuiltinType(tpe)) tpe else Defines.Any
val memberNode_ = nodeInfo.node match {
case TSDeclareMethod | TSDeclareFunction =>
val function = createMethodDefinitionNode(nodeInfo)
val bindingNode = newBindingNode("", "", "")
diffGraph.addEdge(typeDeclNode, bindingNode, EdgeTypes.BINDS)
diffGraph.addEdge(bindingNode, function, EdgeTypes.REF)
val function = createMethodDefinitionNode(nodeInfo)
addModifier(function, nodeInfo.json)
memberNode(nodeInfo, function.name, nodeInfo.code, typeFullName, Seq(function.fullName))
.possibleTypes(possibleTypes)
case ClassMethod | ClassPrivateMethod =>
val function = createMethodAstAndNode(nodeInfo).methodNode
val bindingNode = newBindingNode("", "", "")
diffGraph.addEdge(typeDeclNode, bindingNode, EdgeTypes.BINDS)
diffGraph.addEdge(bindingNode, function, EdgeTypes.REF)
val function = createMethodAstAndNode(nodeInfo).methodNode
addModifier(function, nodeInfo.json)
memberNode(nodeInfo, function.name, nodeInfo.code, typeFullName, Seq(function.fullName))
.possibleTypes(possibleTypes)
Expand Down Expand Up @@ -500,9 +493,9 @@ trait AstForTypesCreator(implicit withSchemaValidation: ValidationMode) { this:
val constructorNode = interfaceConstructor(typeName, tsInterface)
diffGraph.addEdge(constructorNode, NewModifier().modifierType(ModifierTypes.CONSTRUCTOR), EdgeTypes.AST)

val constructorBindingNode = newBindingNode("", "", "")
diffGraph.addEdge(typeDeclNode_, constructorBindingNode, EdgeTypes.BINDS)
diffGraph.addEdge(constructorBindingNode, constructorNode, EdgeTypes.REF)
val memberNode_ =
memberNode(tsInterface, constructorNode.name, constructorNode.code, typeFullName, Seq(constructorNode.fullName))
diffGraph.addEdge(typeDeclNode_, memberNode_, EdgeTypes.AST)

val interfaceBodyElements = classMembers(tsInterface, withConstructor = false)

Expand All @@ -514,9 +507,6 @@ trait AstForTypesCreator(implicit withSchemaValidation: ValidationMode) { this:
val memberNodes = nodeInfo.node match {
case TSCallSignatureDeclaration | TSMethodSignature =>
val functionNode = createMethodDefinitionNode(nodeInfo)
val bindingNode = newBindingNode("", "", "")
diffGraph.addEdge(typeDeclNode_, bindingNode, EdgeTypes.BINDS)
diffGraph.addEdge(bindingNode, functionNode, EdgeTypes.REF)
addModifier(functionNode, nodeInfo.json)
Seq(
memberNode(nodeInfo, functionNode.name, nodeInfo.code, typeFullName, Seq(functionNode.fullName))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ object BabelAst {
object TSIndexSignature extends BabelNode
object TSIndexedAccessType extends TSType
object TSInferType extends TSType
object TSInstantiationExpression extends Expression
object TSInterfaceBody extends BabelNode
object TSInterfaceDeclaration extends BabelNode
object TSIntersectionType extends TSType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,7 @@ class TsAstCreationPassTests extends AstJsSrc2CpgSuite(".ts") {
arg.typeFullName shouldBe Defines.String
arg.code shouldBe "arg: string"
arg.index shouldBe 1
val List(parentTypeDecl) = cpg.typeDecl.name(":program").l
parentTypeDecl.bindsOut.flatMap(_.refOut).l should contain(func)
cpg.method("foo").bindingTypeDecl.fullName.l shouldBe List("Test0.ts::program:foo")
}

"have correct structure for type assertion" in {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,10 @@ class TsClassesAstCreationPassTests extends AstJsSrc2CpgSuite(".ts") {
greeter.fullName shouldBe "Test0.ts::program:Greeter"
greeter.filename shouldBe "Test0.ts"
greeter.file.name.head shouldBe "Test0.ts"
inside(cpg.typeDecl("Greeter").member.l) { case List(greeting, name, propName, foo, anon, toString) =>
inside(cpg.typeDecl("Greeter").member.l) { case List(init, greeting, name, propName, foo, anon, toString) =>
init.name shouldBe "<init>"
init.typeFullName shouldBe "Test0.ts::program:Greeter"
init.dynamicTypeHintFullName shouldBe List("Test0.ts::program:Greeter:<init>")
greeting.name shouldBe "greeting"
greeting.code shouldBe "greeting: string;"
name.name shouldBe "name"
Expand Down
Loading

0 comments on commit cf8d139

Please sign in to comment.