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
3 changes: 3 additions & 0 deletions pathfinder-rules/test/ClassInstanceExpr.cql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM ClassInstanceExpr AS cie
WHERE cie.getClassInstanceExpr().GetClassName() == "Intent"
SELECT cie.getClassInstanceExpr().GetArgs(), cie.getClassInstanceExpr().GetNumArgs(), cie.getClassInstanceExpr().GetArg(0)
10 changes: 9 additions & 1 deletion sourcecode-parser/cmd/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,17 @@ func processQuery(input string, codeGraph *graph.CodeGraph, output string) (stri
verticalLine := "|"
yellowCode := color.New(color.FgYellow).SprintFunc()
greenCode := color.New(color.FgGreen).SprintFunc()
for _, entity := range entities {
for i, entity := range entities {
for _, entityObject := range entity {
header := fmt.Sprintf("\tFile: %s, Line: %s \n", greenCode(entityObject.File), greenCode(entityObject.LineNumber))
// add formatted output to result
output := "\tResult: "
for _, outputObject := range formattedOutput[i] {
output += graph.FormatType(outputObject)
output += " "
output += verticalLine + " "
}
header += output + "\n"
result += header
result += "\n"
codeSnippetArray := strings.Split(entityObject.CodeSnippet, "\n")
Expand Down
4 changes: 2 additions & 2 deletions sourcecode-parser/cmd/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestExecuteCLIQuery(t *testing.T) {
query: "FROM method_declaration AS md WHERE md.getName() == \"onCreateOptionsMenu\" SELECT md.getName()",
output: "",
stdin: false,
expectedOutput: "File: ../../test-src/android/app/src/main/java/com/ivb/udacity/movieListActivity.java, Line: 96 \n\n\t\t 96 | @Override\n\t\t 97 | public boolean onCreateOptionsMenu(Menu menu) {\n\t\t 98 | MenuInflater inflater = getMenuInflater();\n\t\t 99 | inflater.inflate(R.menu.main, menu);\n\t\t 100 | return true;\n\t\t 101 | }",
expectedOutput: "File: ../../test-src/android/app/src/main/java/com/ivb/udacity/movieListActivity.java, Line: 96 \n\tResult: onCreateOptionsMenu | \n\n\t\t 96 | @Override\n\t\t 97 | public boolean onCreateOptionsMenu(Menu menu) {\n\t\t 98 | MenuInflater inflater = getMenuInflater();\n\t\t 99 | inflater.inflate(R.menu.main, menu);\n\t\t 100 | return true;\n\t\t 101 | }",
expectedError: "",
},
{
Expand Down Expand Up @@ -79,7 +79,7 @@ func TestProcessQuery(t *testing.T) {
name: "Basic query",
input: "FROM method_declaration AS md WHERE md.getName() == \"testFunc\" SELECT md.getName()",
output: "",
expectedResult: "\tFile: test.java, Line: 5 \n\n\t\t 5 | public void testFunc() {}\n\n",
expectedResult: "\tFile: test.java, Line: 5 \n\tResult: testFunc | \n\n\t\t 5 | public void testFunc() {}\n\n",
expectedError: "",
},
{
Expand Down
48 changes: 48 additions & 0 deletions sourcecode-parser/graph/construct.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"log"
"os"
"path/filepath"
"strconv"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -43,6 +44,7 @@ type Node struct {
Annotation []string
JavaDoc *model.Javadoc
BinaryExpr *model.BinaryExpr
ClassInstanceExpr *model.ClassInstanceExpr
}

type Edge struct {
Expand Down Expand Up @@ -715,6 +717,52 @@ func buildGraphFromAST(node *sitter.Node, sourceCode []byte, graph *CodeGraph, c
isJavaSourceFile: isJavaSourceFile,
}
graph.AddNode(variableNode)
case "object_creation_expression":
className := ""
classInstanceExpression := model.ClassInstanceExpr{
ClassName: "",
Args: []*model.Expr{},
}
for i := 0; i < int(node.ChildCount()); i++ {
child := node.Child(i)
if child.Type() == "type_identifier" || child.Type() == "scoped_type_identifier" {
className = child.Content(sourceCode)
classInstanceExpression.ClassName = className
}
if child.Type() == "argument_list" {
classInstanceExpression.Args = []*model.Expr{}
for j := 0; j < int(child.ChildCount()); j++ {
argType := child.Child(j).Type()
argumentStopWords := map[string]bool{
"(": true,
")": true,
"{": true,
"}": true,
"[": true,
"]": true,
",": true,
}
if !argumentStopWords[argType] {
argument := &model.Expr{}
argument.Type = child.Child(j).Type()
argument.NodeString = child.Child(j).Content(sourceCode)
classInstanceExpression.Args = append(classInstanceExpression.Args, argument)
}
}
}
}

objectNode := &Node{
ID: GenerateMethodID(className, []string{strconv.Itoa(int(node.StartPoint().Row + 1))}, file),
Type: "ClassInstanceExpr",
Name: className,
CodeSnippet: node.Content(sourceCode),
LineNumber: node.StartPoint().Row + 1,
File: file,
isJavaSourceFile: isJavaSourceFile,
ClassInstanceExpr: &classInstanceExpression,
}
graph.AddNode(objectNode)
}

// Recursively process child nodes
Expand Down
16 changes: 16 additions & 0 deletions sourcecode-parser/graph/construct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,22 @@ func TestBuildGraphFromAST(t *testing.T) {
expectedTypes: []string{"class_declaration", "method_declaration", "block_comment"},
unexpectedTypes: []string{"variable_declaration", "binary_expression"},
},
// add testcase for object creation expression
{
name: "Class with object creation expression",
sourceCode: `
public class ObjectCreationClass {
public static void main(String[] args) {
ObjectCreationClass obj = new ObjectCreationClass();
Socket socket = new Socket("www.google.com", 80);
}
}
`,
expectedNodes: 6,
expectedEdges: 0,
expectedTypes: []string{"class_declaration", "method_declaration", "ClassInstanceExpr"},
unexpectedTypes: []string{"binary_expression"},
},
}

for _, tt := range tests {
Expand Down
32 changes: 25 additions & 7 deletions sourcecode-parser/graph/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,15 @@ func (env *Env) GetRightOperand() string {
return env.Node.BinaryExpr.RightOperand.NodeString
}

func QueryEntities(graph *CodeGraph, query parser.Query) (nodes [][]*Node, output [][]string) {
func (env *Env) GetClassInstanceExpr() *model.ClassInstanceExpr {
return env.Node.ClassInstanceExpr
}

func (env *Env) GetClassInstanceExprName() string {
return env.Node.ClassInstanceExpr.ClassName
}

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

// log query select list alone
Expand All @@ -131,10 +139,10 @@ func QueryEntities(graph *CodeGraph, query parser.Query) (nodes [][]*Node, outpu
return nodes, output
}

func generateOutput(nodeSet [][]*Node, query parser.Query) [][]string {
results := make([][]string, 0, len(nodeSet))
func generateOutput(nodeSet [][]*Node, query parser.Query) [][]interface{} {
results := make([][]interface{}, 0, len(nodeSet))
for _, nodeSet := range nodeSet {
var result []string
var result []interface{}
for _, outputFormat := range query.SelectOutput {
switch outputFormat.Type {
case "string":
Expand All @@ -156,7 +164,7 @@ func generateOutput(nodeSet [][]*Node, query parser.Query) [][]string {
return results
}

func evaluateExpression(node []*Node, expression string, query parser.Query) (string, error) {
func evaluateExpression(node []*Node, expression string, query parser.Query) (interface{}, error) {
env := generateProxyEnvForSet(node, query)

program, err := expr.Compile(expression, expr.Env(env))
Expand All @@ -169,7 +177,7 @@ func evaluateExpression(node []*Node, expression string, query parser.Query) (st
fmt.Println("Error evaluating expression: ", err)
return "", err
}
return output.(string), nil
return output, nil
}

func generateCartesianProduct(graph *CodeGraph, selectList []parser.SelectList, conditions []string) [][]*Node {
Expand All @@ -193,7 +201,8 @@ func generateCartesianProduct(graph *CodeGraph, selectList []parser.SelectList,
}
}
} else {
for _, node := range graph.Nodes {
filteredNodes := graph.FindNodesByType(selectList[0].Entity)
for _, node := range filteredNodes {
query := parser.Query{Expression: condition, SelectList: selectList}
if FilterEntities([]*Node{node}, query) {
typeIndex[node.Type] = appendUnique(typeIndex[node.Type], node)
Expand Down Expand Up @@ -280,6 +289,7 @@ func generateProxyEnv(node *Node, query parser.Query) map[string]interface{} {
orBitwiseExpression := "or_bitwise_expression"
unsignedRightShiftExpression := "unsigned_right_shift_expression"
xorBitwsieExpression := "xor_bitwise_expression"
classInstanceExpression := "ClassInstanceExpr"

// print query select list
for _, entity := range query.SelectList {
Expand Down Expand Up @@ -326,6 +336,8 @@ func generateProxyEnv(node *Node, query parser.Query) map[string]interface{} {
unsignedRightShiftExpression = entity.Alias
case "xor_bitwise_expression":
xorBitwsieExpression = entity.Alias
case "ClassInstanceExpr":
classInstanceExpression = entity.Alias
}
}
env := map[string]interface{}{
Expand Down Expand Up @@ -450,6 +462,12 @@ func generateProxyEnv(node *Node, query parser.Query) map[string]interface{} {
"getOperator": "^",
"toString": proxyenv.ToString,
},
classInstanceExpression: map[string]interface{}{
"getName": proxyenv.GetName,
"getDoc": proxyenv.GetDoc,
"toString": proxyenv.ToString,
"getClassInstanceExpr": proxyenv.GetClassInstanceExpr,
},
}
return env
}
Expand Down
18 changes: 18 additions & 0 deletions sourcecode-parser/graph/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package graph
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
)

Expand All @@ -26,3 +27,20 @@ func appendUnique(slice []*Node, node *Node) []*Node {
}
return append(slice, node)
}

func FormatType(v interface{}) string {
switch val := v.(type) {
case string:
return val
case int, int64:
return fmt.Sprintf("%d", val)
case float32, float64:
return fmt.Sprintf("%.2f", val)
case []interface{}:
//nolint:all
jsonBytes, _ := json.Marshal(val)
return string(jsonBytes)
default:
return fmt.Sprintf("%v", val)
}
}
68 changes: 68 additions & 0 deletions sourcecode-parser/graph/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,71 @@ func isValidHexString(s string) bool {
_, err := hex.DecodeString(s)
return err == nil
}

func TestFormatType(t *testing.T) {
tests := []struct {
name string
input interface{}
want string
}{
{
name: "String input",
input: "test string",
want: "test string",
},
{
name: "Integer input",
input: 42,
want: "42",
},
{
name: "Int64 input",
input: int64(9223372036854775807),
want: "9223372036854775807",
},
{
name: "Float32 input",
input: float32(3.14),
want: "3.14",
},
{
name: "Float64 input",
input: 2.71828,
want: "2.72",
},
{
name: "Slice of integers",
input: []interface{}{1, 2, 3},
want: "[1,2,3]",
},
{
name: "Slice of mixed types",
input: []interface{}{"a", 1, true},
want: `["a",1,true]`,
},
{
name: "Boolean input",
input: true,
want: "true",
},
{
name: "Nil input",
input: nil,
want: "<nil>",
},
{
name: "Struct input",
input: struct{ Name string }{"John"},
want: "{John}",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := FormatType(tt.input)
if got != tt.want {
t.Errorf("FormatType() = %v, want %v", got, tt.want)
}
})
}
}
35 changes: 33 additions & 2 deletions sourcecode-parser/model/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@ func (e *ExprParent) GetNumChildExpr() int64 {

type Expr struct {
ExprParent
kind int
Kind int
Node sitter.Node
NodeString string
Type string
}

func (e *Expr) String() string {
return fmt.Sprintf("Expr(%s)", e.NodeString)
}

func (e *Expr) GetAChildExpr() *Expr {
Expand All @@ -43,7 +48,7 @@ func (e *Expr) GetBoolValue() {
}

func (e *Expr) GetKind() int {
return e.kind
return e.Kind
}

type BinaryExpr struct {
Expand Down Expand Up @@ -278,3 +283,29 @@ type XorBitwiseExpr struct {
func (e *XorBitwiseExpr) GetOp() string {
return e.op
}

type ClassInstanceExpr struct {
Expr
ClassName string
Args []*Expr
}

func (e *ClassInstanceExpr) GetClassName() string {
return e.ClassName
}

func (e *ClassInstanceExpr) GetArgs() []*Expr {
return e.Args
}

func (e *ClassInstanceExpr) GetArg(i int) *Expr {
return e.Args[i]
}

func (e *ClassInstanceExpr) GetNumArgs() int {
return len(e.Args)
}

func (e *ClassInstanceExpr) String() string {
return fmt.Sprintf("ClassInstanceExpr(%s, %v)", e.ClassName, e.Args)
}
Loading