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
16 changes: 16 additions & 0 deletions sourcecode-parser/graph/construct.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type Node struct {
BreakStmt *model.BreakStmt
ContinueStmt *model.ContinueStmt
YieldStmt *model.YieldStmt
AssertStmt *model.AssertStmt
}

type Edge struct {
Expand Down Expand Up @@ -181,6 +182,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 "assert_statement":
assertNode := javalang.ParseAssertStatement(node, sourceCode)
uniqueAssertID := fmt.Sprintf("assert_%d_%d_%s", node.StartPoint().Row+1, node.StartPoint().Column+1, file)
assertStmtNode := &Node{
ID: GenerateSha256(uniqueAssertID),
Type: "AssertStmt",
LineNumber: node.StartPoint().Row + 1,
Name: "AssertStmt",
IsExternal: true,
CodeSnippet: node.Content(sourceCode),
File: file,
isJavaSourceFile: isJavaSourceFile,
AssertStmt: assertNode,
}
graph.AddNode(assertStmtNode)
case "yield_statement":
yieldNode := javalang.ParseYieldStatement(node, sourceCode)
uniqueyieldID := fmt.Sprintf("yield_%d_%d_%s", node.StartPoint().Row+1, node.StartPoint().Column+1, file)
Expand Down
9 changes: 9 additions & 0 deletions sourcecode-parser/graph/java/parse_statement.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,12 @@ func ParseYieldStatement(node *sitter.Node, sourcecode []byte) *model.YieldStmt
yieldStmt.Value = yieldStmtExpr
return yieldStmt
}

func ParseAssertStatement(node *sitter.Node, sourcecode []byte) *model.AssertStmt {
assertStmt := &model.AssertStmt{}
assertStmt.Expr = &model.Expr{NodeString: node.Child(1).Content(sourcecode)}
if node.Child(3) != nil && node.Child(3).Type() == "string_literal" {
assertStmt.Message = &model.Expr{NodeString: node.Child(3).Content(sourcecode)}
}
return assertStmt
}
61 changes: 61 additions & 0 deletions sourcecode-parser/graph/java/parse_statement_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,64 @@ func TestParseYieldStatement(t *testing.T) {
})
}
}

func TestParseAssertStatement(t *testing.T) {
tests := []struct {
name string
input string
expected *model.AssertStmt
}{
{
name: "Simple assert statement without message",
input: "assert x > 0;",
expected: &model.AssertStmt{
Expr: &model.Expr{NodeString: "x > 0"},
Message: nil,
},
},
{
name: "Assert statement with message",
input: "assert condition : \"Value must be positive\";",
expected: &model.AssertStmt{
Expr: &model.Expr{NodeString: "condition"},
Message: &model.Expr{NodeString: "\"Value must be positive\""},
},
},
{
name: "Assert statement with boolean literal",
input: "assert true;",
expected: &model.AssertStmt{
Expr: &model.Expr{NodeString: "true"},
Message: nil,
},
},
{
name: "Assert statement with complex expression",
input: "assert x != null && x.isValid();",
expected: &model.AssertStmt{
Expr: &model.Expr{NodeString: "x != null && x.isValid()"},
Message: nil,
},
},
{
name: "Assert statement with method call and message",
input: "assert obj.validate() : \"Validation failed\";",
expected: &model.AssertStmt{
Expr: &model.Expr{NodeString: "obj.validate()"},
Message: &model.Expr{NodeString: "\"Validation failed\""},
},
},
}

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 := ParseAssertStatement(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 @@ -147,6 +147,10 @@ func (env *Env) GetYieldStmt() *model.YieldStmt {
return env.Node.YieldStmt
}

func (env *Env) GetAssertStmt() *model.AssertStmt {
return env.Node.AssertStmt
}

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

Expand Down Expand Up @@ -325,6 +329,7 @@ func generateProxyEnv(node *Node, query parser.Query) map[string]interface{} {
breakStmt := "BreakStmt"
continueStmt := "ContinueStmt"
yieldStmt := "YieldStmt"
assertStmt := "AssertStmt"

// print query select list
for _, entity := range query.SelectList {
Expand Down Expand Up @@ -387,6 +392,8 @@ func generateProxyEnv(node *Node, query parser.Query) map[string]interface{} {
continueStmt = entity.Alias
case "YieldStmt":
yieldStmt = entity.Alias
case "AssertStmt":
assertStmt = entity.Alias
}
}
env := map[string]interface{}{
Expand Down Expand Up @@ -545,6 +552,10 @@ func generateProxyEnv(node *Node, query parser.Query) map[string]interface{} {
"toString": proxyenv.ToString,
"getYieldStmt": proxyenv.GetYieldStmt,
},
assertStmt: map[string]interface{}{
"toString": proxyenv.ToString,
"getAssertStmt": proxyenv.GetAssertStmt,
},
}
return env
}
Expand Down
40 changes: 40 additions & 0 deletions sourcecode-parser/model/stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,3 +301,43 @@ func (yieldStmt *YieldStmt) ToString() string {
func (yieldStmt *YieldStmt) GetValue() *Expr {
return yieldStmt.Value
}

type AssertStmt struct {
Stmt
Expr *Expr
Message *Expr
}

type IAssertStmt interface {
GetAPrimaryQlClass() string
GetHalsteadID() int
GetPP() string
ToString() string
GetMessage() *Expr
GetExpr() *Expr
}

func (assertStmt *AssertStmt) GetAPrimaryQlClass() string {
return "AssertStmt"
}

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

func (assertStmt *AssertStmt) GetPP() string {
return fmt.Sprintf("assert %s", assertStmt.Expr.NodeString)
}

func (assertStmt *AssertStmt) ToString() string {
return fmt.Sprintf("assert %s", assertStmt.Expr.NodeString)
}

func (assertStmt *AssertStmt) GetMessage() *Expr {
return assertStmt.Message
}

func (assertStmt *AssertStmt) GetExpr() *Expr {
return assertStmt.Expr
}
35 changes: 35 additions & 0 deletions sourcecode-parser/model/stmt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,3 +349,38 @@ func TestYieldStmt_GetPP(t *testing.T) {
assert.Equal(t, "yield \"test string\"", yieldStmt.GetPP())
})
}

func TestAssertStmt_GetMessage(t *testing.T) {
t.Run("GetMessage with non-nil message", func(t *testing.T) {
message := &Expr{NodeString: "Expected value to be positive"}
assertStmt := &AssertStmt{
Message: message,
}
assert.Equal(t, message, assertStmt.GetMessage())
})

t.Run("GetMessage with nil message", func(t *testing.T) {
assertStmt := &AssertStmt{
Message: nil,
}
assert.Nil(t, assertStmt.GetMessage())
})

t.Run("GetMessage with complex expression", func(t *testing.T) {
message := &Expr{NodeString: "String.format(\"Value %d should be greater than zero\", value)"}
assertStmt := &AssertStmt{
Message: message,
}
assert.Equal(t, message, assertStmt.GetMessage())
})

t.Run("GetMessage preserves expression reference", func(t *testing.T) {
message := &Expr{NodeString: "Initial message"}
assertStmt := &AssertStmt{
Message: message,
}
retrievedMessage := assertStmt.GetMessage()
message.NodeString = "Modified message"
assert.Equal(t, "Modified message", retrievedMessage.NodeString)
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public void onBackPressed() {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
assert id > 0 : "Invalid item id";
if (id == android.R.id.home) {
onBackPressed();
return true;
Expand Down
Loading