Skip to content

Commit

Permalink
feature: 🍺 Support for BreakStmt (#174)
Browse files Browse the repository at this point in the history
* 🐳 added  support

* 🐳 added  support
  • Loading branch information
shivasurya authored Nov 4, 2024
1 parent d6d1f4d commit d8bbf0c
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 3 deletions.
18 changes: 18 additions & 0 deletions sourcecode-parser/graph/construct.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"sync"
"time"

javalang "github.com/shivasurya/code-pathfinder/sourcecode-parser/graph/java"

"github.com/shivasurya/code-pathfinder/sourcecode-parser/model"
"github.com/smacker/go-tree-sitter/java"

Expand Down Expand Up @@ -48,6 +50,7 @@ type Node struct {
WhileStmt *model.WhileStmt
DoStmt *model.DoStmt
ForStmt *model.ForStmt
BreakStmt *model.BreakStmt
}

type Edge struct {
Expand Down Expand Up @@ -176,6 +179,21 @@ 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 "break_statement":
breakNode := javalang.ParseBreakStatement(node, sourceCode)
uniquebreakstmtID := fmt.Sprintf("breakstmt_%d_%d_%s", node.StartPoint().Row+1, node.StartPoint().Column+1, file)
breakStmtNode := &Node{
ID: GenerateSha256(uniquebreakstmtID),
Type: "BreakStmt",
LineNumber: node.StartPoint().Row + 1,
Name: "BreakStmt",
IsExternal: true,
CodeSnippet: node.Content(sourceCode),
File: file,
isJavaSourceFile: isJavaSourceFile,
BreakStmt: breakNode,
}
graph.AddNode(breakStmtNode)
case "if_statement":
ifNode := model.IfStmt{}
// get the condition of the if statement
Expand Down
9 changes: 7 additions & 2 deletions sourcecode-parser/graph/construct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -753,11 +753,16 @@ func TestBuildGraphFromAST(t *testing.T) {
int i = 1 | 1;
int j = 1 ^ 1;
int l = 1 >>> 1;
outerlabel:
while (a > 0) {
a--;
if (a == 0) {
break outerlabel;
}
}
for (int i = 0; i < 10; i++) {
System.out.println(i);
break;
}
do {
System.out.println("Hello, World!");
Expand All @@ -771,9 +776,9 @@ func TestBuildGraphFromAST(t *testing.T) {
}
}
`,
expectedNodes: 63,
expectedNodes: 68,
expectedEdges: 4,
expectedTypes: []string{"class_declaration", "method_declaration", "binary_expression", "comp_expression", "and_expression", "or_expression", "IfStmt", "ForStmt", "WhileStmt", "DoStmt"},
expectedTypes: []string{"class_declaration", "method_declaration", "binary_expression", "comp_expression", "and_expression", "or_expression", "IfStmt", "ForStmt", "WhileStmt", "DoStmt", "BreakStmt"},
unexpectedTypes: []string{""},
},
{
Expand Down
17 changes: 17 additions & 0 deletions sourcecode-parser/graph/java/parse_statement.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package java

import (
"github.com/shivasurya/code-pathfinder/sourcecode-parser/model"
sitter "github.com/smacker/go-tree-sitter"
)

func ParseBreakStatement(node *sitter.Node, sourcecode []byte) *model.BreakStmt {
breakStmt := &model.BreakStmt{}
// get identifier if present child
for i := 0; i < int(node.ChildCount()); i++ {
if node.Child(i).Type() == "identifier" {
breakStmt.Label = node.Child(i).Content(sourcecode)
}
}
return breakStmt
}
41 changes: 41 additions & 0 deletions sourcecode-parser/graph/java/parse_statement_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package java

import (
"github.com/smacker/go-tree-sitter/java"
"testing"

"github.com/shivasurya/code-pathfinder/sourcecode-parser/model"
sitter "github.com/smacker/go-tree-sitter"
"github.com/stretchr/testify/assert"
)

func TestParseBreakStatement(t *testing.T) {
tests := []struct {
name string
input string
expected *model.BreakStmt
}{
{
name: "Simple break statement without label",
input: "break;",
expected: &model.BreakStmt{Label: ""},
},
{
name: "Break statement with label",
input: "break myLabel;",
expected: &model.BreakStmt{Label: "myLabel"},
},
}

parser := sitter.NewParser()
parser.SetLanguage(java.GetLanguage())

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tree := parser.Parse(nil, []byte(tt.input))
node := tree.RootNode().Child(0)
result := ParseBreakStatement(node, []byte(tt.input))
assert.Equal(t, tt.expected, result)
})
}
}
11 changes: 11 additions & 0 deletions sourcecode-parser/graph/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ func (env *Env) GetForStmt() *model.ForStmt {
return env.Node.ForStmt
}

func (env *Env) GetBreakStmt() *model.BreakStmt {
return env.Node.BreakStmt
}

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

Expand Down Expand Up @@ -310,6 +314,7 @@ func generateProxyEnv(node *Node, query parser.Query) map[string]interface{} {
whileStmt := "WhileStmt"
doStmt := "DoStmt"
forStmt := "ForStmt"
breakStmt := "BreakStmt"

// print query select list
for _, entity := range query.SelectList {
Expand Down Expand Up @@ -366,6 +371,8 @@ func generateProxyEnv(node *Node, query parser.Query) map[string]interface{} {
doStmt = entity.Alias
case "ForStmt":
forStmt = entity.Alias
case "BreakStmt":
breakStmt = entity.Alias
}
}
env := map[string]interface{}{
Expand Down Expand Up @@ -512,6 +519,10 @@ func generateProxyEnv(node *Node, query parser.Query) map[string]interface{} {
"getForStmt": proxyenv.GetForStmt,
"toString": proxyenv.ToString,
},
breakStmt: map[string]interface{}{
"toString": proxyenv.ToString,
"getBreakStmt": proxyenv.GetBreakStmt,
},
}
return env
}
Expand Down
61 changes: 61 additions & 0 deletions sourcecode-parser/model/stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,64 @@ func (whileStmt *WhileStmt) GetPP() string {
func (whileStmt *WhileStmt) ToString() string {
return fmt.Sprintf("while (%s) %s", whileStmt.Condition.NodeString, whileStmt.Stmt.NodeString)
}

type ILabeledStmt interface {
GetAPrimaryQlClass() string
GetHalsteadID() int
GetLabel() *LabeledStmt
GetPP() string
ToString() string
}

type LabeledStmt struct {
Stmt
Label *LabeledStmt
}

type JumpStmt struct {
Stmt
}

type IJumpStmt interface {
GetTarget() *StmtParent
GetTargetLabel() *LabeledStmt
}

type IBreakStmt interface {
GetAPrimaryQlClass() string
GetHalsteadID() int
GetLabel() string
hasLabel() bool
GetPP() string
ToString() string
}

type BreakStmt struct {
JumpStmt
Label string
}

func (breakStmt *BreakStmt) GetAPrimaryQlClass() string {
return "BreakStmt"
}

func (breakStmt *BreakStmt) GetHalsteadID() int {
// TODO: Implement Halstead ID calculation for BreakStmt
return 0
}

func (breakStmt *BreakStmt) GetPP() string {
return fmt.Sprintf("break (%s)", breakStmt.Label)
}

func (breakStmt *BreakStmt) ToString() string {
return fmt.Sprintf("break (%s)", breakStmt.Label)
}

func (breakStmt *BreakStmt) hasLabel() bool {
return breakStmt.Label != ""
}

func (breakStmt *BreakStmt) GetLabel() string {
return breakStmt.Label
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ protected void onCreate(Bundle savedInstanceState) {
ServerSocket serverSocket = new ServerSocket(80);

movieGeneralModal moviegeneralModal = (movieGeneralModal) intent.getSerializableExtra("DATA_MOVIE");

outlabel:
if (savedInstanceState == null) {

movieDetailFragment fragment = new movieDetailFragment();
break outlabel;
fragment.setMovieData(moviegeneralModal);
getSupportFragmentManager().beginTransaction()
.add(R.id.movie_detail_container, fragment)
Expand Down

0 comments on commit d8bbf0c

Please sign in to comment.