From 81f964074e65deea25cf3f1300e8e040f1b410a5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Filip=20Hed=C3=A9n?= <filip.heden@debricked.com>
Date: Tue, 30 Jul 2024 14:37:38 +0200
Subject: [PATCH] Add parsing of relative paths for go callgraphs

---
 .../callgraph/language/golang/callgraph.go    | 13 +++++++--
 .../language/golang/callgraph_test.go         | 29 +++++++++++++++++++
 .../callgraph/language/golang/strategy.go     |  3 --
 3 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/internal/callgraph/language/golang/callgraph.go b/internal/callgraph/language/golang/callgraph.go
index b47231ae..7f35ebd1 100644
--- a/internal/callgraph/language/golang/callgraph.go
+++ b/internal/callgraph/language/golang/callgraph.go
@@ -106,7 +106,6 @@ func (cg *CallgraphBuilder) createPackageConfig() (*packages.Config, []string) {
 		Tests: cg.includeTests,
 		Dir:   cg.workingDirectory,
 	}
-
 	args := []string{cg.mainFile}
 
 	return cfg, args
@@ -171,6 +170,14 @@ func IsApplicationNode(filename string, pwd string) bool {
 	return false
 }
 
+func RelativePath(filename string, pwd string) string {
+	if len(filename) > len(pwd) && filename[:len(pwd)] == pwd {
+		return filename[len(pwd)+1:] // +1 for "/"
+	}
+
+	return filename
+}
+
 func (cg *CallgraphBuilder) outputCallGraph(icg *callgraph.Graph, prog *ssa.Program) error {
 	data := Edge{fset: prog.Fset}
 	pwd, err := os.Getwd()
@@ -190,14 +197,14 @@ func (cg *CallgraphBuilder) outputCallGraph(icg *callgraph.Graph, prog *ssa.Prog
 		var ok bool
 		if callerNode, ok = cg.cgModel.Nodes[callerSymbol]; !ok {
 			callerFilename := data.CallerFilename()
-			callerNode = cg.cgModel.AddNode(callerFilename, data.Caller.Name(), callerSymbol, IsApplicationNode(callerFilename, pwd), false, -1, -1)
+			callerNode = cg.cgModel.AddNode(RelativePath(callerFilename, pwd), data.Caller.Name(), callerSymbol, IsApplicationNode(callerFilename, pwd), false, -1, -1)
 		}
 
 		var calleeNode *model.Node
 		calleeSymbol := cleanSymbol(edge.Callee.Func.String())
 		if calleeNode, ok = cg.cgModel.Nodes[calleeSymbol]; !ok {
 			calleeFilename := data.CalleeFilename()
-			calleeNode = cg.cgModel.AddNode(calleeFilename, data.Callee.Name(), calleeSymbol, IsApplicationNode(calleeFilename, pwd), false, -1, -1)
+			calleeNode = cg.cgModel.AddNode(RelativePath(calleeFilename, pwd), data.Callee.Name(), calleeSymbol, IsApplicationNode(calleeFilename, pwd), false, -1, -1)
 		}
 
 		cg.cgModel.AddEdge(callerNode, calleeNode, data.CallLine())
diff --git a/internal/callgraph/language/golang/callgraph_test.go b/internal/callgraph/language/golang/callgraph_test.go
index 1fc220a7..77920f71 100644
--- a/internal/callgraph/language/golang/callgraph_test.go
+++ b/internal/callgraph/language/golang/callgraph_test.go
@@ -133,3 +133,32 @@ func TestIsApplicationNode(t *testing.T) {
 	}
 
 }
+
+func TestRelativeFilename(t *testing.T) {
+	tests := []struct {
+		name string
+		pwd  string
+		in   string
+		want string
+	}{
+		{
+			name: "Test with standard library",
+			pwd:  "testdata/fixture",
+			in:   "testdata/fixture/main.go.Println",
+			want: "main.go.Println",
+		},
+		{
+			name: "Test with non-standard library",
+			pwd:  "testdata/fixture",
+			in:   "github.com/spf13/afero/mem.File.Open",
+			want: "github.com/spf13/afero/mem.File.Open",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			assert.Equal(t, tt.want, RelativePath(tt.in, tt.pwd))
+		})
+	}
+
+}
diff --git a/internal/callgraph/language/golang/strategy.go b/internal/callgraph/language/golang/strategy.go
index cd6d302d..a67dff18 100644
--- a/internal/callgraph/language/golang/strategy.go
+++ b/internal/callgraph/language/golang/strategy.go
@@ -32,7 +32,6 @@ func (s Strategy) Invoke() ([]job.IJob, error) {
 	}
 
 	for _, path := range s.paths {
-
 		files, err := s.finder.FindFiles([]string{path}, s.exclusions, s.inclusions)
 		if err != nil {
 			strategyWarning("Error while finding files: " + err.Error())
@@ -52,10 +51,8 @@ func (s Strategy) Invoke() ([]job.IJob, error) {
 		}
 
 		for _, rootFilePath := range roots {
-
 			rootFileDir := filepath.Dir(rootFilePath)
 			rootFile := filepath.Base(rootFilePath)
-
 			jobs = append(jobs, NewJob(
 				rootFileDir,
 				rootFile,