Skip to content

Commit

Permalink
feature: IfStmt, DoStmt, WhileStmt, ForStmt and Generic Statement s…
Browse files Browse the repository at this point in the history
…upport (#173)

* ⛵ added statement model

* ⛵ added statement model

* added do while statement

* added if stmt

* 🚢 added  support query

* 🐳 added WhileStmt support

* 🚀 supported do-while statement

* 🐳 added for loop statement support

* 🐳 add tests

* 🐳 add tests
  • Loading branch information
shivasurya authored Nov 4, 2024
1 parent 5094373 commit d6d1f4d
Show file tree
Hide file tree
Showing 16 changed files with 1,114 additions and 3 deletions.
108 changes: 108 additions & 0 deletions sourcecode-parser/graph/construct.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ type Node struct {
JavaDoc *model.Javadoc
BinaryExpr *model.BinaryExpr
ClassInstanceExpr *model.ClassInstanceExpr
IfStmt *model.IfStmt
WhileStmt *model.WhileStmt
DoStmt *model.DoStmt
ForStmt *model.ForStmt
}

type Edge struct {
Expand Down Expand Up @@ -172,6 +176,110 @@ func parseJavadocTags(commentContent string) *model.Javadoc {
func buildGraphFromAST(node *sitter.Node, sourceCode []byte, graph *CodeGraph, currentContext *Node, file string) {
isJavaSourceFile := isJavaSourceFile(file)
switch node.Type() {
case "if_statement":
ifNode := model.IfStmt{}
// get the condition of the if statement
conditionNode := node.Child(1)
if conditionNode != nil {
ifNode.Condition = &model.Expr{Node: *conditionNode, NodeString: conditionNode.Content(sourceCode)}
}
// get the then block of the if statement
thenNode := node.Child(2)
if thenNode != nil {
ifNode.Then = model.Stmt{NodeString: thenNode.Content(sourceCode)}
}
// get the else block of the if statement
elseNode := node.Child(4)
if elseNode != nil {
ifNode.Else = model.Stmt{NodeString: elseNode.Content(sourceCode)}
}

methodID := fmt.Sprintf("ifstmt_%d_%d_%s", node.StartPoint().Row+1, node.StartPoint().Column+1, file)
// add node to graph
ifStmtNode := &Node{
ID: GenerateSha256(methodID),
Type: "IfStmt",
Name: "IfStmt",
IsExternal: true,
CodeSnippet: node.Content(sourceCode),
LineNumber: node.StartPoint().Row + 1,
File: file,
isJavaSourceFile: isJavaSourceFile,
IfStmt: &ifNode,
}
graph.AddNode(ifStmtNode)
case "while_statement":
whileNode := model.WhileStmt{}
// get the condition of the while statement
conditionNode := node.Child(1)
if conditionNode != nil {
whileNode.Condition = &model.Expr{Node: *conditionNode, NodeString: conditionNode.Content(sourceCode)}
}
methodID := fmt.Sprintf("while_stmt_%d_%d_%s", node.StartPoint().Row+1, node.StartPoint().Column+1, file)
// add node to graph
whileStmtNode := &Node{
ID: GenerateSha256(methodID),
Type: "WhileStmt",
Name: "WhileStmt",
IsExternal: true,
CodeSnippet: node.Content(sourceCode),
LineNumber: node.StartPoint().Row + 1,
File: file,
isJavaSourceFile: isJavaSourceFile,
WhileStmt: &whileNode,
}
graph.AddNode(whileStmtNode)
case "do_statement":
doWhileNode := model.DoStmt{}
// get the condition of the while statement
conditionNode := node.Child(2)
if conditionNode != nil {
doWhileNode.Condition = &model.Expr{Node: *conditionNode, NodeString: conditionNode.Content(sourceCode)}
}
methodID := fmt.Sprintf("dowhile_stmt_%d_%d_%s", node.StartPoint().Row+1, node.StartPoint().Column+1, file)
// add node to graph
doWhileStmtNode := &Node{
ID: GenerateSha256(methodID),
Type: "DoStmt",
Name: "DoStmt",
IsExternal: true,
CodeSnippet: node.Content(sourceCode),
LineNumber: node.StartPoint().Row + 1,
File: file,
isJavaSourceFile: isJavaSourceFile,
DoStmt: &doWhileNode,
}
graph.AddNode(doWhileStmtNode)
case "for_statement":
forNode := model.ForStmt{}
// get the condition of the while statement
initNode := node.ChildByFieldName("init")
if initNode != nil {
forNode.Init = &model.Expr{Node: *initNode, NodeString: initNode.Content(sourceCode)}
}
conditionNode := node.ChildByFieldName("condition")
if conditionNode != nil {
forNode.Condition = &model.Expr{Node: *conditionNode, NodeString: conditionNode.Content(sourceCode)}
}
incrementNode := node.ChildByFieldName("increment")
if incrementNode != nil {
forNode.Increment = &model.Expr{Node: *incrementNode, NodeString: incrementNode.Content(sourceCode)}
}

methodID := fmt.Sprintf("for_stmt_%d_%d_%s", node.StartPoint().Row+1, node.StartPoint().Column+1, file)
// add node to graph
forStmtNode := &Node{
ID: GenerateSha256(methodID),
Type: "ForStmt",
Name: "ForStmt",
IsExternal: true,
CodeSnippet: node.Content(sourceCode),
LineNumber: node.StartPoint().Row + 1,
File: file,
isJavaSourceFile: isJavaSourceFile,
ForStmt: &forNode,
}
graph.AddNode(forStmtNode)
case "binary_expression":
leftNode := node.ChildByFieldName("left")
rightNode := node.ChildByFieldName("right")
Expand Down
20 changes: 17 additions & 3 deletions sourcecode-parser/graph/construct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -753,13 +753,27 @@ func TestBuildGraphFromAST(t *testing.T) {
int i = 1 | 1;
int j = 1 ^ 1;
int l = 1 >>> 1;
while (a > 0) {
a--;
}
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
do {
System.out.println("Hello, World!");
} while (a > 0);
if (a < 0) {
System.out.println("Negative number");
} else {
System.out.println("Positive number");
}
return (5 > 3) && (10 <= 20) || (15 != 12) || (20 > 15);
}
}
`,
expectedNodes: 49,
expectedEdges: 0,
expectedTypes: []string{"class_declaration", "method_declaration", "binary_expression", "comp_expression", "and_expression", "or_expression"},
expectedNodes: 63,
expectedEdges: 4,
expectedTypes: []string{"class_declaration", "method_declaration", "binary_expression", "comp_expression", "and_expression", "or_expression", "IfStmt", "ForStmt", "WhileStmt", "DoStmt"},
unexpectedTypes: []string{""},
},
{
Expand Down
44 changes: 44 additions & 0 deletions sourcecode-parser/graph/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,22 @@ func (env *Env) GetClassInstanceExprName() string {
return env.Node.ClassInstanceExpr.ClassName
}

func (env *Env) GetIfStmt() *model.IfStmt {
return env.Node.IfStmt
}

func (env *Env) GetWhileStmt() *model.WhileStmt {
return env.Node.WhileStmt
}

func (env *Env) GetDoStmt() *model.DoStmt {
return env.Node.DoStmt
}

func (env *Env) GetForStmt() *model.ForStmt {
return env.Node.ForStmt
}

func QueryEntities(graph *CodeGraph, query parser.Query) (nodes [][]*Node, output [][]interface{}) {
result := make([][]*Node, 0)

Expand Down Expand Up @@ -290,6 +306,10 @@ func generateProxyEnv(node *Node, query parser.Query) map[string]interface{} {
unsignedRightShiftExpression := "unsigned_right_shift_expression"
xorBitwsieExpression := "xor_bitwise_expression"
classInstanceExpression := "ClassInstanceExpr"
ifStmt := "IfStmt"
whileStmt := "WhileStmt"
doStmt := "DoStmt"
forStmt := "ForStmt"

// print query select list
for _, entity := range query.SelectList {
Expand Down Expand Up @@ -338,6 +358,14 @@ func generateProxyEnv(node *Node, query parser.Query) map[string]interface{} {
xorBitwsieExpression = entity.Alias
case "ClassInstanceExpr":
classInstanceExpression = entity.Alias
case "IfStmt":
ifStmt = entity.Alias
case "WhileStmt":
whileStmt = entity.Alias
case "DoStmt":
doStmt = entity.Alias
case "ForStmt":
forStmt = entity.Alias
}
}
env := map[string]interface{}{
Expand Down Expand Up @@ -468,6 +496,22 @@ func generateProxyEnv(node *Node, query parser.Query) map[string]interface{} {
"toString": proxyenv.ToString,
"getClassInstanceExpr": proxyenv.GetClassInstanceExpr,
},
ifStmt: map[string]interface{}{
"getIfStmt": proxyenv.GetIfStmt,
"toString": proxyenv.ToString,
},
whileStmt: map[string]interface{}{
"getWhileStmt": proxyenv.GetWhileStmt,
"toString": proxyenv.ToString,
},
doStmt: map[string]interface{}{
"getDoStmt": proxyenv.GetDoStmt,
"toString": proxyenv.ToString,
},
forStmt: map[string]interface{}{
"getForStmt": proxyenv.GetForStmt,
"toString": proxyenv.ToString,
},
}
return env
}
Expand Down
118 changes: 118 additions & 0 deletions sourcecode-parser/model/container.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package model

type Container struct {
Top
}

func (c *Container) ToString() string {
return ""
}

type File struct {
Container
File string
}

func (f *File) IsSourceFile() bool {
// check if file extension is .java
if f.File[len(f.File)-5:] == ".java" || f.File[len(f.File)-4:] == ".kt" {
return true
}
return false
}

func (f *File) IsJavaSourceFile() bool {
return f.File[len(f.File)-5:] == ".java"
}

func (f *File) IsKotlinSourceFile() bool {
return f.File[len(f.File)-5:] == ".kt"
}

func (f *File) GetAPrimaryQlClass() string {
return "File"
}

type CompilationUnit struct {
File
module Module
CuPackage Package
Name string
}

func (c *CompilationUnit) GetAPrimaryQlClass() string {
return "CompilationUnit"
}

func (c *CompilationUnit) GetModule() Module {
return c.module
}

func (c *CompilationUnit) GetName() string {
return c.Name
}

func (c *CompilationUnit) GetPackage() Package {
return c.CuPackage
}

func (c *CompilationUnit) HasName(name string) bool {
return c.Name == name
}

func (c *CompilationUnit) ToString() string {
return c.Name
}

type JarFile struct {
File
JarFile string
ImplementationVersion string
ManifestEntryAttributes map[string]map[string]string
ManifestMainAttributes map[string]string
SpecificationVersion string
}

func (j *JarFile) GetAPrimaryQlClass() string {
return "JarFile"
}

func (j *JarFile) GetJarFile() string {
return j.JarFile
}

func (j *JarFile) GetImplementationVersion() string {
return j.ImplementationVersion
}

func (j *JarFile) GetManifestEntryAttributes(entry, key string) (string, bool) {
if attributes, exists := j.ManifestEntryAttributes[entry]; exists {
if value, keyExists := attributes[key]; keyExists {
return value, true
}
}
return "", false
}

func (j *JarFile) GetManifestMainAttributes(key string) (string, bool) {
if value, exists := j.ManifestMainAttributes[key]; exists {
return value, true
}
return "", false
}

func (j *JarFile) GetSpecificationVersion() string {
return j.SpecificationVersion
}

type Package struct {
Package string
}

func (p *Package) GetAPrimaryQlClass() string {
return "Package"
}

func (p *Package) GetURL() string {
return p.Package
}
Loading

0 comments on commit d6d1f4d

Please sign in to comment.