Skip to content

Commit

Permalink
Added Annotation attr (#45)
Browse files Browse the repository at this point in the history
Added annotation attr and now we could query

- FIND method_declaration WHERE annotation = "@deprecated" AND has_access = "true"
  • Loading branch information
shivasurya authored Jul 1, 2024
1 parent 8e00f0e commit ed04b21
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 42 deletions.
91 changes: 49 additions & 42 deletions sourcecode-parser/construct.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type GraphNode struct {
isJavaSourceFile bool
JavaDocTag []*model.JavadocTag
ThrowsExceptions []string
Annotation []string
}

type GraphEdge struct {
Expand Down Expand Up @@ -168,13 +169,13 @@ func buildGraphFromAST(node *sitter.Node, sourceCode []byte, graph *CodeGraph, c
javadocTags = parseJavadocTags(commentContent)
}
}
methodName, methodID := extractMethodName(node, sourceCode)
invokedNode, exists := graph.Nodes[methodID]
methodName, methodID := extractMethodName(node, sourceCode, file)
modifiers := ""
returnType := ""
throws := []string{}
methodArgumentType := []string{}
methodArgumentValue := []string{}
annotationMarkers := []string{}

for i := 0; i < int(node.ChildCount()); i++ {
childNode := node.Child(i)
Expand All @@ -191,6 +192,11 @@ func buildGraphFromAST(node *sitter.Node, sourceCode []byte, graph *CodeGraph, c
}
case "modifiers":
modifiers = childNode.Content(sourceCode)
for j := 0; j < int(childNode.ChildCount()); j++ {
if childNode.Child(j).Type() == "marker_annotation" {
annotationMarkers = append(annotationMarkers, childNode.Child(j).Content(sourceCode))
}
}
case "void_type", "type_identifier":
// get return type of method
returnType = childNode.Content(sourceCode)
Expand All @@ -209,30 +215,27 @@ func buildGraphFromAST(node *sitter.Node, sourceCode []byte, graph *CodeGraph, c
}
}

if !exists || (invokedNode.ID != methodID) {
invokedNode = &GraphNode{
ID: methodID, // In a real scenario, you would construct a unique ID, possibly using the method signature
Type: "method_declaration",
Name: methodName,
CodeSnippet: node.Content(sourceCode),
LineNumber: node.StartPoint().Row + 1, // Lines start from 0 in the AST
Modifier: extractVisibilityModifier(modifiers),
ReturnType: returnType,
MethodArgumentsType: methodArgumentType,
MethodArgumentsValue: methodArgumentValue,
File: file,
isJavaSourceFile: isJavaSourceFile,
JavaDocTag: javadocTags,
ThrowsExceptions: throws,
// CodeSnippet and LineNumber are skipped as per the requirement
}
invokedNode := &GraphNode{
ID: methodID, // In a real scenario, you would construct a unique ID, possibly using the method signature
Type: "method_declaration",
Name: methodName,
CodeSnippet: node.Content(sourceCode),
LineNumber: node.StartPoint().Row + 1, // Lines start from 0 in the AST
Modifier: extractVisibilityModifier(modifiers),
ReturnType: returnType,
MethodArgumentsType: methodArgumentType,
MethodArgumentsValue: methodArgumentValue,
File: file,
isJavaSourceFile: isJavaSourceFile,
JavaDocTag: javadocTags,
ThrowsExceptions: throws,
Annotation: annotationMarkers,
}
graph.AddNode(invokedNode)
currentContext = invokedNode // Update context to the new method

case "method_invocation":
methodName, methodID := extractMethodName(node, sourceCode) // Implement this
invokedNode, exists := graph.Nodes[methodID]
methodName, methodID := extractMethodName(node, sourceCode, file)
arguments := []string{}
// get argument list from arguments node iterate for child node
for i := 0; i < int(node.ChildCount()); i++ {
Expand All @@ -247,21 +250,18 @@ func buildGraphFromAST(node *sitter.Node, sourceCode []byte, graph *CodeGraph, c
}
}

if !exists || (invokedNode.ID != methodID) {
// Create a placeholder node for external or inbuilt method
invokedNode = &GraphNode{
ID: methodID,
Type: "method_invocation",
Name: methodName,
IsExternal: true,
CodeSnippet: node.Content(sourceCode),
LineNumber: node.StartPoint().Row + 1, // Lines start from 0 in the AST
MethodArgumentsValue: arguments,
File: file,
isJavaSourceFile: isJavaSourceFile,
}
graph.AddNode(invokedNode)
invokedNode := &GraphNode{
ID: methodID,
Type: "method_invocation",
Name: methodName,
IsExternal: true,
CodeSnippet: node.Content(sourceCode),
LineNumber: node.StartPoint().Row + 1, // Lines start from 0 in the AST
MethodArgumentsValue: arguments,
File: file,
isJavaSourceFile: isJavaSourceFile,
}
graph.AddNode(invokedNode)

if currentContext != nil {
graph.AddEdge(currentContext, invokedNode)
Expand All @@ -278,11 +278,17 @@ func buildGraphFromAST(node *sitter.Node, sourceCode []byte, graph *CodeGraph, c
packageName := ""
accessModifier := ""
superClass := ""
annotationMarkers := []string{}
implementedInterface := []string{}
for i := 0; i < int(node.ChildCount()); i++ {
child := node.Child(i)
if child.Type() == "modifiers" {
accessModifier = child.Content(sourceCode)
for j := 0; j < int(child.ChildCount()); j++ {
if child.Child(j).Type() == "marker_annotation" {
annotationMarkers = append(annotationMarkers, child.Child(j).Content(sourceCode))
}
}
}
if child.Type() == "superclass" {
for j := 0; j < int(child.ChildCount()); j++ {
Expand All @@ -302,7 +308,7 @@ func buildGraphFromAST(node *sitter.Node, sourceCode []byte, graph *CodeGraph, c
}
}
classNode := &GraphNode{
ID: generateMethodID(className, []string{}),
ID: generateMethodID(className, []string{}, file),
Type: "class_declaration",
Name: className,
CodeSnippet: node.Content(sourceCode),
Expand All @@ -314,6 +320,7 @@ func buildGraphFromAST(node *sitter.Node, sourceCode []byte, graph *CodeGraph, c
File: file,
isJavaSourceFile: isJavaSourceFile,
JavaDocTag: javadocTags,
Annotation: annotationMarkers,
}
graph.AddNode(classNode)
case "block_comment":
Expand All @@ -323,7 +330,7 @@ func buildGraphFromAST(node *sitter.Node, sourceCode []byte, graph *CodeGraph, c
javadocTags := parseJavadocTags(commentContent)

commentNode := &GraphNode{
ID: generateMethodID(node.Content(sourceCode), []string{}),
ID: generateMethodID(node.Content(sourceCode), []string{}, file),
Type: "block_comment",
CodeSnippet: commentContent,
LineNumber: node.StartPoint().Row + 1,
Expand Down Expand Up @@ -378,7 +385,7 @@ func buildGraphFromAST(node *sitter.Node, sourceCode []byte, graph *CodeGraph, c
}
// Create a new node for the variable
variableNode := &GraphNode{
ID: generateMethodID(variableName, []string{}),
ID: generateMethodID(variableName, []string{}, file),
Type: "variable_declaration",
Name: variableName,
CodeSnippet: node.Content(sourceCode),
Expand Down Expand Up @@ -419,15 +426,15 @@ func buildGraphFromAST(node *sitter.Node, sourceCode []byte, graph *CodeGraph, c
}

// write a function to generate unique method id from method name, class name, and package name, parameters, and return type.
func generateMethodID(methodName string, parameters []string) string {
func generateMethodID(methodName string, parameters []string, sourceFile string) string {
// Example: Use the node type and its start byte position in the source code to generate a unique ID
hashInput := fmt.Sprintf("%s-%s", methodName, parameters)
hashInput := fmt.Sprintf("%s-%s-%s", methodName, parameters, sourceFile)
hash := sha256.Sum256([]byte(hashInput))
return hex.EncodeToString(hash[:])
}

//nolint:all
func extractMethodName(node *sitter.Node, sourceCode []byte) (string, string) {
func extractMethodName(node *sitter.Node, sourceCode []byte, filepath string) (string, string) {
var methodID string

// if the child node is method_declaration, extract method name, modifiers, parameters, and return type
Expand Down Expand Up @@ -479,7 +486,7 @@ func extractMethodName(node *sitter.Node, sourceCode []byte) (string, string) {

}
}
methodID = generateMethodID(methodName, parameters)
methodID = generateMethodID(methodName, parameters, filepath)
return methodName, methodID
}

Expand Down
41 changes: 41 additions & 0 deletions sourcecode-parser/model/javadoc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package model

import (
"testing"
)

func TestNewJavadocTag(t *testing.T) {
tagName := "author"
text := "John Doe"
docType := "class"

tag := NewJavadocTag(tagName, text, docType)

if tag.TagName != tagName {
t.Errorf("Expected TagName to be %s, got %s", tagName, tag.TagName)
}

if tag.Text != text {
t.Errorf("Expected Text to be %s, got %s", text, tag.Text)
}

if tag.DocType != docType {
t.Errorf("Expected DocType to be %s, got %s", docType, tag.DocType)
}
}

func TestNewJavadocTagWithEmptyValues(t *testing.T) {
tag := NewJavadocTag("", "", "")

if tag.TagName != "" {
t.Errorf("Expected TagName to be empty, got %s", tag.TagName)
}

if tag.Text != "" {
t.Errorf("Expected Text to be empty, got %s", tag.Text)
}

if tag.DocType != "" {
t.Errorf("Expected DocType to be empty, got %s", tag.DocType)
}
}
7 changes: 7 additions & 0 deletions sourcecode-parser/source_sink.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ func (gnc *GraphNodeContext) GetValue(key, val string) string {
switch key {
case "visibility":
return gnc.Node.Modifier
case "annotation":
for _, annotation := range gnc.Node.Annotation {
if annotation == val {
return annotation
}
}
return ""
case "returntype":
return gnc.Node.ReturnType
case "name":
Expand Down

0 comments on commit ed04b21

Please sign in to comment.