Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,27 @@ trait AstForStatementsCreator(implicit withSchemaValidation: ValidationMode) { t

protected def astForStatement(nodeInfo: DotNetNodeInfo): Seq[Ast] = {
nodeInfo.node match {
case ExpressionStatement => astForExpressionStatement(nodeInfo)
case GlobalStatement => astForGlobalStatement(nodeInfo)
case IfStatement => astForIfStatement(nodeInfo)
case ThrowStatement => astForThrowStatement(nodeInfo)
case TryStatement => astForTryStatement(nodeInfo)
case ForEachStatement => astForForEachStatement(nodeInfo)
case ForStatement => astForForStatement(nodeInfo)
case DoStatement => astForDoStatement(nodeInfo)
case WhileStatement => astForWhileStatement(nodeInfo)
case SwitchStatement => astForSwitchStatement(nodeInfo)
case UsingStatement => astForUsingStatement(nodeInfo)
case _: JumpStatement => astForJumpStatement(nodeInfo)
case _ => notHandledYet(nodeInfo)
case ExpressionStatement => astForExpressionStatement(nodeInfo)
case GlobalStatement => astForGlobalStatement(nodeInfo)
case IfStatement => astForIfStatement(nodeInfo)
case ThrowStatement => astForThrowStatement(nodeInfo)
case TryStatement => astForTryStatement(nodeInfo)
case ForEachStatement => astForForEachStatement(nodeInfo)
case ForStatement => astForForStatement(nodeInfo)
case DoStatement => astForDoStatement(nodeInfo)
case WhileStatement => astForWhileStatement(nodeInfo)
case SwitchStatement => astForSwitchStatement(nodeInfo)
case UsingStatement => astForUsingStatement(nodeInfo)
case LocalFunctionStatement => astForLocalFunctionStatement(nodeInfo)
case _: JumpStatement => astForJumpStatement(nodeInfo)
case _ => notHandledYet(nodeInfo)
}
}

private def astForLocalFunctionStatement(nodeInfo: DotNetNodeInfo): Seq[Ast] = {
astForMethodDeclaration(nodeInfo)
}

private def astForSwitchLabel(labelNode: DotNetNodeInfo): Seq[Ast] = {
val caseNode = jumpTargetNode(labelNode, "case", labelNode.code)
labelNode.node match
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.joern.csharpsrc2cpg.querying.ast

import io.joern.csharpsrc2cpg.testfixtures.CSharpCode2CpgFixture
import io.shiftleft.codepropertygraph.generated.ModifierTypes
import io.shiftleft.codepropertygraph.generated.nodes.Return
import io.shiftleft.semanticcpg.language.*

class MethodTests extends CSharpCode2CpgFixture {
Expand Down Expand Up @@ -107,4 +108,63 @@ class MethodTests extends CSharpCode2CpgFixture {
)
}
}

"standalone method declaration inside a top-level method" should {
val cpg = code("""
|int MyMain()
|{
| int MySubMethod() {return 1;}
|}
|""".stripMargin)

"have correct properties for the nested method" in {
inside(cpg.method.nameExact("MySubMethod").l) {
case sub :: Nil =>
sub.fullName shouldBe "Test0_cs_Program.<Main>$.MyMain.MySubMethod:System.Int32()"
sub.signature shouldBe "System.Int32()"
sub.modifier.modifierType.sorted.l shouldBe List(ModifierTypes.INTERNAL)
sub.methodReturn.typeFullName shouldBe "System.Int32"
sub.parentBlock.method.l shouldBe cpg.method.fullNameExact("Test0_cs_Program.<Main>$.MyMain:System.Int32()").l
case xs => fail(s"Expected single MySubMethod METHOD, but got $xs")
}
}

"have correct body for the nested method" in {
inside(cpg.method.nameExact("MySubMethod").block.astChildren.l) {
case (ret: Return) :: Nil => ret.code shouldBe "return 1;"
case xs => fail(s"Expected single RETURN node, but got $xs")
}
}
}

"standalone method declaration inside a class method" should {
val cpg = code("""
|class MyClass
|{
| int MyMain()
| {
| int MySubMethod() {return 1;}
| }
|}
|""".stripMargin)

"have correct properties for the nested method" in {
inside(cpg.method.nameExact("MySubMethod").l) {
case sub :: Nil =>
sub.fullName shouldBe "MyClass.MyMain.MySubMethod:System.Int32()"
sub.signature shouldBe "System.Int32()"
sub.modifier.modifierType.sorted.l shouldBe List(ModifierTypes.INTERNAL)
sub.methodReturn.typeFullName shouldBe "System.Int32"
sub.parentBlock.method.l shouldBe cpg.method.fullNameExact("MyClass.MyMain:System.Int32()").l
case xs => fail(s"Expected single MySubMethod METHOD, but got $xs")
}
}

"have correct body for the nested method" in {
inside(cpg.method.nameExact("MySubMethod").block.astChildren.l) {
case (ret: Return) :: Nil => ret.code shouldBe "return 1;"
case xs => fail(s"Expected single RETURN node, but got $xs")
}
}
}
}
Loading