Repository: goplus/gop
Pull request #1552 (2023-11-22 03:31:57)

cl: config add option FileLineRoot for comment line


Patch:
diff --git a/cl/compile.go b/cl/compile.go
index d6d64bba..24837727 100644
--- a/cl/compile.go
+++ b/cl/compile.go
@@ -22,6 +22,7 @@ import (
 	"go/types"
 	"log"
 	"os"
+	"path/filepath"
 	"reflect"
 	"sort"
 	"strings"
@@ -205,6 +206,9 @@ type Config struct {
 	// RelativePath = true means to generate file line comments with relative file path.
 	RelativePath bool
 
+	// FileLineRoot set means generate file line comments start with root path.
+	FileLineRoot string
+
 	// NoAutoGenMain = true means not to auto generate main func is no entry.
 	NoAutoGenMain bool
 
@@ -370,6 +374,9 @@ type pkgCtx struct {
 	generics map[string]bool // generic type record
 	idents   []*ast.Ident    // toType ident recored
 	inInst   int             // toType in generic instance
+
+	fileLineRoot       string // comment file line start root
+	fileLineWorkingDir string // comment file line working dir
 }
 
 type pkgImp struct {
@@ -510,6 +517,10 @@ func NewPackage(pkgPath string, pkg *ast.Package, conf *Config) (p *gox.Package,
 		fset: fset,
 		syms: make(map[string]loader), nodeInterp: interp, generics: make(map[string]bool),
 	}
+	if conf.FileLineRoot != "" {
+		ctx.fileLineRoot, _ = filepath.Abs(conf.FileLineRoot)
+		ctx.fileLineWorkingDir, _ = filepath.Abs(workingDir)
+	}
 	confGox := &gox.Config{
 		Types:           conf.Types,
 		Fset:            fset,
diff --git a/cl/stmt.go b/cl/stmt.go
index f0bb0cff..805646b5 100644
--- a/cl/stmt.go
+++ b/cl/stmt.go
@@ -42,11 +42,23 @@ func relFile(dir string, file string) string {
 	return file
 }
 
+func offsetFileLine(ctx *blockCtx, file string) string {
+	if !filepath.IsAbs(file) {
+		file = filepath.Join(ctx.fileLineWorkingDir, file)
+	}
+	if ret, err := filepath.Rel(ctx.fileLineRoot, file); err == nil {
+		return ret
+	}
+	return file
+}
+
 func commentStmt(ctx *blockCtx, stmt ast.Stmt) {
 	if ctx.fileLine {
 		start := stmt.Pos()
 		pos := ctx.fset.Position(start)
-		if ctx.relativePath {
+		if ctx.fileLineRoot != "" {
+			pos.Filename = offsetFileLine(ctx, pos.Filename)
+		} else if ctx.relativePath {
 			pos.Filename = relFile(ctx.targetDir, pos.Filename)
 		}
 		line := fmt.Sprintf("\n//line %s:%d:1", pos.Filename, pos.Line)
@@ -61,7 +73,9 @@ func commentFunc(ctx *blockCtx, fn *gox.Func, decl *ast.FuncDecl) {
 	start := decl.Name.Pos()
 	if ctx.fileLine && start != token.NoPos {
 		pos := ctx.fset.Position(start)
-		if ctx.relativePath {
+		if ctx.fileLineRoot != "" {
+			pos.Filename = offsetFileLine(ctx, pos.Filename)
+		} else if ctx.relativePath {
 			pos.Filename = relFile(ctx.targetDir, pos.Filename)
 		}
 		var line string
diff --git a/load.go b/load.go
index a26bad87..3e8ae230 100644
--- a/load.go
+++ b/load.go
@@ -187,11 +187,12 @@ func LoadDir(dir string, conf *Config, genTestPkg bool, promptGenGo ...bool) (ou
 
 	var pkgTest *ast.Package
 	var clConf = &cl.Config{
-		WorkingDir:  dir,
-		Fset:        fset,
-		Importer:    imp,
-		LookupClass: mod.LookupClass,
-		LookupPub:   c2go.LookupPub(mod),
+		WorkingDir:   dir,
+		Fset:         fset,
+		Importer:     imp,
+		LookupClass:  mod.LookupClass,
+		LookupPub:    c2go.LookupPub(mod),
+		FileLineRoot: mod.Root(),
 	}
 	for name, pkg := range pkgs {
 		if strings.HasSuffix(name, "_test") {


Test patch:
diff --git a/cl/compile_test.go b/cl/compile_test.go
index e058472a..52022aeb 100644
--- a/cl/compile_test.go
+++ b/cl/compile_test.go
@@ -19,6 +19,7 @@ package cl_test
 import (
 	"bytes"
 	"os"
+	"runtime"
 	"strings"
 	"sync"
 	"testing"
@@ -4652,3 +4653,64 @@ func main() {
 }
 `)
 }
+
+func TestCommentLineRoot(t *testing.T) {
+	conf := *gblConf
+	conf.NoFileLine = false
+	conf.FileLineRoot = "/foo/root"
+	conf.WorkingDir = "/foo"
+	conf.TargetDir = "/foo"
+	var src = `
+type Point struct {
+	x int
+	y int
+}
+
+func (pt *Point) Test() {
+	println(pt.x, pt.y)
+}
+
+// testPoint is test point
+func testPoint() {
+	var pt Point
+	pt.Test()
+}
+
+println "hello"
+testPoint()
+`
+	var expected = `package main
+
+import "fmt"
+
+type Point struct {
+	x int
+	y int
+}
+//line ../bar.gop:7:1
+func (pt *Point) Test() {
+//line ../bar.gop:8:1
+	fmt.Println(pt.x, pt.y)
+}
+// testPoint is test point
+//
+//line ../bar.gop:12:1
+func testPoint() {
+//line ../bar.gop:13:1
+	var pt Point
+//line ../bar.gop:14:1
+	pt.Test()
+}
+//line ../bar.gop:17
+func main() {
+//line ../bar.gop:17:1
+	fmt.Println("hello")
+//line ../bar.gop:18:1
+	testPoint()
+}
+`
+	if runtime.GOOS == "windows" {
+		expected = strings.Replace(expected, "../", `..\foo\`, -1)
+	}
+	gopClTestEx(t, &conf, "main", src, expected)
+}