From 7cf287892e09d89bade2e992fbb0ac6ee8dede30 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Nov 2023 07:07:44 +0000 Subject: [PATCH 01/14] build(deps): bump golang.org/x/tools from 0.14.0 to 0.15.0 Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.14.0 to 0.15.0. - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/compare/v0.14.0...v0.15.0) --- updated-dependencies: - dependency-name: golang.org/x/tools dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index f9c821701..991808f3e 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/goplus/gox v1.13.0 github.com/goplus/mod v0.11.9 github.com/qiniu/x v1.13.1 - golang.org/x/tools v0.14.0 + golang.org/x/tools v0.15.0 ) require ( @@ -16,5 +16,5 @@ require ( github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect golang.org/x/mod v0.14.0 // indirect - golang.org/x/sys v0.13.0 // indirect + golang.org/x/sys v0.14.0 // indirect ) diff --git a/go.sum b/go.sum index 682743b0b..a09aa0885 100644 --- a/go.sum +++ b/go.sum @@ -45,8 +45,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -55,8 +55,9 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -74,6 +75,7 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= +golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 805158b0284bbec822dea8deb789d4069dbfad18 Mon Sep 17 00:00:00 2001 From: visualfc Date: Wed, 15 Nov 2023 15:34:16 +0800 Subject: [PATCH 02/14] x/typesutil: add test --- x/typesutil/check_test.go | 144 ++++++++++++ x/typesutil/exprstring_test.go | 118 ++++++++++ x/typesutil/info_test.go | 389 +++++++++++++++++++++++++++++++++ 3 files changed, 651 insertions(+) create mode 100644 x/typesutil/check_test.go create mode 100644 x/typesutil/exprstring_test.go create mode 100644 x/typesutil/info_test.go diff --git a/x/typesutil/check_test.go b/x/typesutil/check_test.go new file mode 100644 index 000000000..518a0d563 --- /dev/null +++ b/x/typesutil/check_test.go @@ -0,0 +1,144 @@ +package typesutil_test + +import ( + goast "go/ast" + "go/importer" + goparser "go/parser" + "go/types" + "os" + "path/filepath" + "testing" + + "github.com/goplus/gop/ast" + "github.com/goplus/gop/parser" + "github.com/goplus/gop/token" + "github.com/goplus/gop/x/typesutil" + "github.com/goplus/mod/gopmod" +) + +func init() { + if os.Getenv("GOPROOT") == "" { + dir, _ := os.Getwd() + os.Setenv("GOPROOT", filepath.Clean(filepath.Join(dir, "./../.."))) + } + typesutil.SetDebug(typesutil.DbgFlagDefault) +} + +func loadFiles(fset *token.FileSet, file string, src interface{}, goxfile string, goxsrc interface{}, gofile string, gosrc interface{}) ([]*ast.File, []*goast.File, error) { + var files []*ast.File + var gofiles []*goast.File + if file != "" { + f, err := parser.ParseFile(fset, file, src, 0) + if err != nil { + return nil, nil, err + } + files = append(files, f) + } + if goxfile != "" { + f, err := parser.ParseFile(fset, goxfile, goxsrc, parser.ParseGoPlusClass) + if err != nil { + return nil, nil, err + } + files = append(files, f) + } + if gofile != "" { + f, err := goparser.ParseFile(fset, gofile, gosrc, 0) + if err != nil { + return nil, nil, err + } + gofiles = append(gofiles, f) + } + return files, gofiles, nil +} + +func checkFiles(fset *token.FileSet, file string, src interface{}, goxfile string, goxsrc interface{}, gofile string, gosrc interface{}) (*typesutil.Info, *types.Info, error) { + files, gofiles, err := loadFiles(fset, file, src, goxfile, goxsrc, gofile, gosrc) + if err != nil { + return nil, nil, err + } + conf := &types.Config{} + conf.Importer = importer.Default() + chkOpts := &typesutil.Config{ + Types: types.NewPackage("main", "main"), + Fset: fset, + Mod: gopmod.Default, + } + info := &typesutil.Info{ + Types: make(map[ast.Expr]types.TypeAndValue), + Defs: make(map[*ast.Ident]types.Object), + Uses: make(map[*ast.Ident]types.Object), + Implicits: make(map[ast.Node]types.Object), + Selections: make(map[*ast.SelectorExpr]*types.Selection), + Scopes: make(map[ast.Node]*types.Scope), + } + ginfo := &types.Info{ + Types: make(map[goast.Expr]types.TypeAndValue), + Defs: make(map[*goast.Ident]types.Object), + Uses: make(map[*goast.Ident]types.Object), + Implicits: make(map[goast.Node]types.Object), + Selections: make(map[*goast.SelectorExpr]*types.Selection), + Scopes: make(map[goast.Node]*types.Scope), + } + check := typesutil.NewChecker(conf, chkOpts, ginfo, info) + err = check.Files(gofiles, files) + return info, ginfo, err +} + +func TestCheckFiles(t *testing.T) { + fset := token.NewFileSet() + info, ginfo, err := checkFiles(fset, "main.gop", ` +type Point struct { + x int + y int +} +pt := &Point{} +pt.x = 100 +pt.y = 200 +println(pt) +println(GoPoint{100,200}) +println(&Rect{100,200}) +`, "Rect.gox", ` +var ( + x int + y int +) +`, "util.go", `package main +type GoPoint struct { + x int + y int +} +`) + if err != nil || info == nil || ginfo == nil { + t.Fatalf("check failed: %v", err) + } +} + +func TestCheckGoFiles(t *testing.T) { + fset := token.NewFileSet() + info, ginfo, err := checkFiles(fset, "", "", "", "", "main.go", `package main +type GoPoint struct { + x int + y int +} +func main() { +} +`) + if err != nil || info == nil || ginfo == nil { + t.Fatalf("check failed: %v", err) + } +} + +func TestCheckError(t *testing.T) { + fset := token.NewFileSet() + _, _, err := checkFiles(fset, "main.gop", ` +type Point struct { + x int + y int +} +pt := &Point1{} +println(pt) +`, "", "", "", "") + if err == nil { + t.Fatal("no error") + } +} diff --git a/x/typesutil/exprstring_test.go b/x/typesutil/exprstring_test.go new file mode 100644 index 000000000..e88d925fd --- /dev/null +++ b/x/typesutil/exprstring_test.go @@ -0,0 +1,118 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package typesutil_test + +import ( + "testing" + + "github.com/goplus/gop/parser" + "github.com/goplus/gop/x/typesutil" +) + +type testEntry struct { + src, str string +} + +// dup returns a testEntry where both src and str are the same. +func dup(s string) testEntry { + return testEntry{s, s} +} + +var testExprs = []testEntry{ + // basic type literals + dup("x"), + dup("true"), + dup("42"), + dup("3.1415"), + dup("2.71828i"), + dup(`'a'`), + dup(`"foo"`), + dup("`bar`"), + + // func and composite literals + {"func(){}", "(func() literal)"}, + {"func(x int) complex128 {}", "(func(x int) complex128 literal)"}, + {"[]int{1, 2, 3}", "[]int{…}"}, + + // type expressions + dup("[1 << 10]byte"), + dup("[]int"), + dup("*int"), + dup("struct{x int}"), + dup("func()"), + dup("func(int, float32) string"), + dup("interface{m()}"), + dup("interface{m() string; n(x int)}"), + + dup("map[string]int"), + dup("chan E"), + dup("<-chan E"), + dup("chan<- E"), + + // non-type expressions + dup("(x)"), + dup("x.f"), + dup("a[i]"), + + dup("s[:]"), + dup("s[i:]"), + dup("s[:j]"), + dup("s[i:j]"), + dup("s[:j:k]"), + dup("s[i:j:k]"), + + dup("x.(T)"), + + dup("x.([10]int)"), + dup("x.([...]int)"), + + dup("x.(struct{})"), + dup("x.(struct{x int; y, z float32; E})"), + + dup("x.(func())"), + dup("x.(func(x int))"), + dup("x.(func() int)"), + dup("x.(func(x, y int, z float32) (r int))"), + dup("x.(func(a, b, c int))"), + dup("x.(func(x ...T))"), + + dup("x.(interface{})"), + dup("x.(interface{m(); n(x int); E})"), + dup("x.(interface{m(); n(x int) T; E; F})"), + + dup("x.(map[K]V)"), + + dup("x.(chan E)"), + dup("x.(<-chan E)"), + dup("x.(chan<- chan int)"), + dup("x.(chan<- <-chan int)"), + dup("x.(<-chan chan int)"), + dup("x.(chan (<-chan int))"), + + dup("f()"), + dup("f(x)"), + dup("int(x)"), + dup("f(x, x + y)"), + dup("f(s...)"), + dup("f(a, s...)"), + + dup("*x"), + dup("&x"), + dup("x + y"), + dup("x + y << (2 * s)"), +} + +func TestExprString(t *testing.T) { + for _, test := range testExprs { + x, err := parser.ParseExpr(test.src) + if err != nil { + t.Errorf("%s: %s", test.src, err) + continue + } + if got := typesutil.ExprString(x); got != test.str { + t.Errorf("%s: got %s, want %s", test.src, got, test.str) + } + } +} diff --git a/x/typesutil/info_test.go b/x/typesutil/info_test.go new file mode 100644 index 000000000..38d654918 --- /dev/null +++ b/x/typesutil/info_test.go @@ -0,0 +1,389 @@ +package typesutil_test + +import ( + "fmt" + + goast "go/ast" + "go/constant" + goformat "go/format" + goparser "go/parser" + + "go/importer" + "go/types" + "sort" + "strings" + "testing" + "unsafe" + + "github.com/goplus/gop/ast" + "github.com/goplus/gop/format" + "github.com/goplus/gop/parser" + "github.com/goplus/gop/token" + "github.com/goplus/gop/x/typesutil" + "github.com/goplus/mod/gopmod" +) + +func parserSource(fset *token.FileSet, filename string, src interface{}, mode parser.Mode) (*typesutil.Info, error) { + f, err := parser.ParseEntry(fset, filename, src, parser.Config{ + Mode: mode, + }) + if err != nil { + return nil, err + } + + conf := &types.Config{} + conf.Importer = importer.Default() + chkOpts := &typesutil.Config{ + Types: types.NewPackage("main", "main"), + Fset: fset, + Mod: gopmod.Default, + } + info := &typesutil.Info{ + Types: make(map[ast.Expr]types.TypeAndValue), + Defs: make(map[*ast.Ident]types.Object), + Uses: make(map[*ast.Ident]types.Object), + Implicits: make(map[ast.Node]types.Object), + Selections: make(map[*ast.SelectorExpr]*types.Selection), + Scopes: make(map[ast.Node]*types.Scope), + } + check := typesutil.NewChecker(conf, chkOpts, nil, info) + err = check.Files(nil, []*ast.File{f}) + return info, err +} + +func parserGoSource(fset *token.FileSet, filename string, src interface{}, mode goparser.Mode) (*types.Info, error) { + f, err := goparser.ParseFile(fset, filename, src, mode) + if err != nil { + return nil, err + } + + conf := &types.Config{} + conf.Importer = importer.Default() + info := &types.Info{ + Types: make(map[goast.Expr]types.TypeAndValue), + Defs: make(map[*goast.Ident]types.Object), + Uses: make(map[*goast.Ident]types.Object), + Implicits: make(map[goast.Node]types.Object), + Selections: make(map[*goast.SelectorExpr]*types.Selection), + Scopes: make(map[goast.Node]*types.Scope), + } + pkg := types.NewPackage("main", "main") + check := types.NewChecker(conf, fset, pkg, info) + err = check.Files([]*goast.File{f}) + return info, err +} + +func testInfo(t *testing.T, src interface{}) { + fset := token.NewFileSet() + info, err := parserSource(fset, "main.gop", src, parser.ParseComments) + if err != nil { + t.Fatal("parserSource error", err) + } + goinfo, err := parserGoSource(fset, "main.go", src, goparser.ParseComments) + if err != nil { + t.Fatal("parserGoSource error", err) + } + // TODO check types + //testItems(t, "types", typesList(fset, info.Types), goTypesList(fset, goinfo.Types)) + testItems(t, "defs", defsList(fset, info.Defs, true), goDefsList(fset, goinfo.Defs, true)) + testItems(t, "uses", usesList(fset, info.Uses), goUsesList(fset, goinfo.Uses)) + // TODO check selections + //testItems(t, "selections", selectionList(fset, info.Selections), goSelectionList(fset, goinfo.Selections)) +} + +func testItems(t *testing.T, name string, items []string, goitems []string) { + text := strings.Join(items, "\n") + gotext := strings.Join(goitems, "\n") + if len(items) != len(goitems) || text != gotext { + t.Errorf(`====== check %v error (Go+ count: %v, Go count %v) ====== +------ Go+ ------ +%v +------ Go ------ +%v +`, + name, len(items), len(goitems), + text, gotext) + } else { + t.Log(fmt.Sprintf(`====== check %v pass (count: %v) ====== +%v +`, name, len(items), text)) + } +} + +func sortItems(items []string) []string { + sort.Strings(items) + for i := 0; i < len(items); i++ { + items[i] = fmt.Sprintf("%03v: %v", i, items[i]) + } + return items +} + +func typesList(fset *token.FileSet, types map[ast.Expr]types.TypeAndValue) []string { + var items []string + for expr, tv := range types { + var buf strings.Builder + posn := fset.Position(expr.Pos()) + tvstr := tv.Type.String() + if tv.Value != nil { + tvstr += " = " + tv.Value.String() + } + // line:col | expr | mode : type = value + fmt.Fprintf(&buf, "%2d:%2d | %-19s %-30T | %-7s : %s | %v", + posn.Line, posn.Column, exprString(fset, expr), expr, + mode(tv), tvstr, (*TypeAndValue)(unsafe.Pointer(&tv)).mode) + items = append(items, buf.String()) + } + return sortItems(items) +} + +func goTypesList(fset *token.FileSet, types map[goast.Expr]types.TypeAndValue) []string { + var items []string + for expr, tv := range types { + var buf strings.Builder + posn := fset.Position(expr.Pos()) + tvstr := tv.Type.String() + if tv.Value != nil { + tvstr += " = " + tv.Value.String() + } + // line:col | expr | mode : type = value + fmt.Fprintf(&buf, "%2d:%2d | %-19s %-30T | %-7s : %s | %v", + posn.Line, posn.Column, goexprString(fset, expr), expr, + mode(tv), tvstr, (*TypeAndValue)(unsafe.Pointer(&tv)).mode) + items = append(items, buf.String()) + } + return sortItems(items) +} + +func defsList(fset *token.FileSet, uses map[*ast.Ident]types.Object, skipNil bool) []string { + var items []string + for expr, obj := range uses { + if skipNil && obj == nil { + continue + } + var buf strings.Builder + posn := fset.Position(expr.Pos()) + // line:col | expr | mode : type = value + fmt.Fprintf(&buf, "%2d:%2d | %-19s | %s", + posn.Line, posn.Column, expr, + obj) + items = append(items, buf.String()) + } + return sortItems(items) +} + +func goDefsList(fset *token.FileSet, uses map[*goast.Ident]types.Object, skipNil bool) []string { + var items []string + for expr, obj := range uses { + if skipNil && obj == nil { + continue // skip nil object + } + var buf strings.Builder + posn := fset.Position(expr.Pos()) + // line:col | expr | mode : type = value + fmt.Fprintf(&buf, "%2d:%2d | %-19s | %s", + posn.Line, posn.Column, expr, + obj) + items = append(items, buf.String()) + } + return sortItems(items) +} + +func usesList(fset *token.FileSet, uses map[*ast.Ident]types.Object) []string { + var items []string + for expr, obj := range uses { + var buf strings.Builder + posn := fset.Position(expr.Pos()) + // line:col | expr | mode : type = value + fmt.Fprintf(&buf, "%2d:%2d | %-19s | %s", + posn.Line, posn.Column, expr, + obj) + items = append(items, buf.String()) + } + return sortItems(items) +} + +func goUsesList(fset *token.FileSet, uses map[*goast.Ident]types.Object) []string { + var items []string + for expr, obj := range uses { + if obj == nil { + continue // skip nil object + } + var buf strings.Builder + posn := fset.Position(expr.Pos()) + // line:col | expr | mode : type = value + fmt.Fprintf(&buf, "%2d:%2d | %-19s | %s", + posn.Line, posn.Column, expr, + obj) + items = append(items, buf.String()) + } + return sortItems(items) +} + +func selectionList(fset *token.FileSet, sels map[*ast.SelectorExpr]*types.Selection) []string { + var items []string + for expr, sel := range sels { + var buf strings.Builder + posn := fset.Position(expr.Pos()) + // line:col | expr | mode : type = value + fmt.Fprintf(&buf, "%2d:%2d | %-19s | %s", + posn.Line, posn.Column, exprString(fset, expr), + sel) + items = append(items, buf.String()) + } + return sortItems(items) +} + +func goSelectionList(fset *token.FileSet, sels map[*goast.SelectorExpr]*types.Selection) []string { + var items []string + for expr, sel := range sels { + var buf strings.Builder + posn := fset.Position(expr.Pos()) + // line:col | expr | mode : type = value + fmt.Fprintf(&buf, "%2d:%2d | %-19s | %s", + posn.Line, posn.Column, goexprString(fset, expr), + sel) + items = append(items, buf.String()) + } + return sortItems(items) +} + +func mode(tv types.TypeAndValue) string { + switch { + case tv.IsVoid(): + return "void" + case tv.IsType(): + return "type" + case tv.IsBuiltin(): + return "builtin" + case tv.IsNil(): + return "nil" + case tv.Assignable(): + if tv.Addressable() { + return "var" + } + return "mapindex" + case tv.IsValue(): + return "value" + default: + return "unknown" + } +} + +func exprString(fset *token.FileSet, expr ast.Expr) string { + var buf strings.Builder + format.Node(&buf, fset, expr) + return buf.String() +} + +func goexprString(fset *token.FileSet, expr goast.Expr) string { + var buf strings.Builder + goformat.Node(&buf, fset, expr) + return buf.String() +} + +type operandMode byte + +const ( + invalid operandMode = iota // operand is invalid + novalue // operand represents no value (result of a function call w/o result) + builtin // operand is a built-in function + typexpr // operand is a type + constant_ // operand is a constant; the operand's typ is a Basic type + variable // operand is an addressable variable + mapindex // operand is a map index expression (acts like a variable on lhs, commaok on rhs of an assignment) + value // operand is a computed value + commaok // like value, but operand may be used in a comma,ok expression + commaerr // like commaok, but second value is error, not boolean + cgofunc // operand is a cgo function +) + +func (v operandMode) String() string { + return operandModeString[int(v)] +} + +var operandModeString = [...]string{ + invalid: "invalid operand", + novalue: "no value", + builtin: "built-in", + typexpr: "type", + constant_: "constant", + variable: "variable", + mapindex: "map index expression", + value: "value", + commaok: "comma, ok expression", + commaerr: "comma, error expression", + cgofunc: "cgo function", +} + +type TypeAndValue struct { + mode operandMode + Type types.Type + Value constant.Value +} + +func TestVarTypes(t *testing.T) { + testInfo(t, `package main +type T struct { + x int + y int +} +var v *int = nil +var v1 []int; +var v2 map[int8]string; +var v3 struct{}; +var v4 *T = &T{100,200}; +`) +} + +func _TestStruct(t *testing.T) { + testInfo(t, `package main + +type Person struct { + name string + age int8 +} + +func test() { + p := Person{ + name: "jack", + } + _ = p.name +} +`) +} + +func _TestStruct2(t *testing.T) { + testInfo(t, `package main + +type Person struct { + name string + age int8 +} + +func test() { + p := Person{ + name: "jack", + } + p.name = "name" +} +`) +} + +func _TestStruct3(t *testing.T) { + testInfo(t, `package main + +import "fmt" + +type Person struct { + name string + age int8 +} + +func test() { + p := Person{ + name: "jack", + } + fmt.Println(p) +} +`) +} From d6fa59a8218ee68d9fadfff22c27831704a274c0 Mon Sep 17 00:00:00 2001 From: visualfc Date: Wed, 15 Nov 2023 20:16:25 +0800 Subject: [PATCH 03/14] x --- x/typesutil/check_test.go | 51 ++++++++++++++++++++++++++++++++++++--- x/typesutil/imp_test.go | 17 +++++++++++++ 2 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 x/typesutil/imp_test.go diff --git a/x/typesutil/check_test.go b/x/typesutil/check_test.go index 518a0d563..fbbbe0acb 100644 --- a/x/typesutil/check_test.go +++ b/x/typesutil/check_test.go @@ -5,6 +5,7 @@ import ( "go/importer" goparser "go/parser" "go/types" + "log" "os" "path/filepath" "testing" @@ -56,8 +57,15 @@ func checkFiles(fset *token.FileSet, file string, src interface{}, goxfile strin if err != nil { return nil, nil, err } + return checkInfo(fset, files, gofiles) +} + +func checkInfo(fset *token.FileSet, files []*ast.File, gofiles []*goast.File) (*typesutil.Info, *types.Info, error) { conf := &types.Config{} conf.Importer = importer.Default() + conf.Error = func(err error) { + log.Println(err) + } chkOpts := &typesutil.Config{ Types: types.NewPackage("main", "main"), Fset: fset, @@ -80,13 +88,15 @@ func checkFiles(fset *token.FileSet, file string, src interface{}, goxfile strin Scopes: make(map[goast.Node]*types.Scope), } check := typesutil.NewChecker(conf, chkOpts, ginfo, info) - err = check.Files(gofiles, files) + err := check.Files(gofiles, files) return info, ginfo, err } func TestCheckFiles(t *testing.T) { fset := token.NewFileSet() info, ginfo, err := checkFiles(fset, "main.gop", ` +import "fmt" + type Point struct { x int y int @@ -94,23 +104,50 @@ type Point struct { pt := &Point{} pt.x = 100 pt.y = 200 -println(pt) -println(GoPoint{100,200}) -println(&Rect{100,200}) +fmt.Println(pt) + +gopt := GoPoint{100,200} +gopt.Test() +gotest() +fmt.Println(GoValue) +fmt.Println(&Rect{100,200}) `, "Rect.gox", ` var ( x int y int ) `, "util.go", `package main +var GoValue string type GoPoint struct { x int y int } +func (p *GoPoint) Test() { +} +func gotest() { +} `) if err != nil || info == nil || ginfo == nil { t.Fatalf("check failed: %v", err) } + + for def, obj := range info.Defs { + o := info.ObjectOf(def) + if o != obj { + t.Fatal("bad obj", o) + } + } + for use, obj := range info.Uses { + o := info.ObjectOf(use) + if o.String() != obj.String() { + t.Fatal("bad obj", o) + } + typ := info.TypeOf(use) + if typ.String() != obj.Type().String() { + t.Fatal("bad typ", typ) + } + } + } func TestCheckGoFiles(t *testing.T) { @@ -137,6 +174,12 @@ type Point struct { } pt := &Point1{} println(pt) +`, "", "", "", "") + if err == nil { + t.Fatal("no error") + } + _, _, err = checkFiles(fset, "main.gop", ` +var i int = "hello" `, "", "", "", "") if err == nil { t.Fatal("no error") diff --git a/x/typesutil/imp_test.go b/x/typesutil/imp_test.go new file mode 100644 index 000000000..f68e6e104 --- /dev/null +++ b/x/typesutil/imp_test.go @@ -0,0 +1,17 @@ +package typesutil + +import ( + "go/token" + "testing" +) + +func TestNilImport(t *testing.T) { + _, err := (&nilImporter{}).Import("fmt") + if err == nil { + t.Fatal("no error") + } + imp := newImporter(nil, nil, nil, token.NewFileSet()) + if imp.(*importer).imp == nil { + t.Fatal("nilImporter") + } +} From 43da068a7d993ee742ef1c9ef5194464ec1cc136 Mon Sep 17 00:00:00 2001 From: visualfc Date: Wed, 15 Nov 2023 20:42:35 +0800 Subject: [PATCH 04/14] x --- x/typesutil/imp_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/x/typesutil/imp_test.go b/x/typesutil/imp_test.go index f68e6e104..9751a4ed6 100644 --- a/x/typesutil/imp_test.go +++ b/x/typesutil/imp_test.go @@ -14,4 +14,7 @@ func TestNilImport(t *testing.T) { if imp.(*importer).imp == nil { t.Fatal("nilImporter") } + if imp.(*importer).gop == nil { + t.Fatal("gopenv.Get") + } } From 414c905d07df96e51d2d74890767af8a6c0c7158 Mon Sep 17 00:00:00 2001 From: visualfc Date: Thu, 16 Nov 2023 08:53:18 +0800 Subject: [PATCH 05/14] cl/internal/typesutil: update TypeAndValue --- cl/compile.go | 3 +- cl/expr.go | 43 ++++++++++++++++---- cl/func_type_and_var.go | 15 ++++++- cl/internal/typesutil/api.go | 65 ++++++++++++++++++++++++++++--- cl/internal/typesutil/api_test.go | 52 ++++++++++++++++++++++--- x/typesutil/info_test.go | 2 +- 6 files changed, 157 insertions(+), 23 deletions(-) diff --git a/cl/compile.go b/cl/compile.go index bdb9d3d22..d6d64bba0 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -28,6 +28,7 @@ import ( "github.com/goplus/gop/ast" "github.com/goplus/gop/ast/fromgo" + "github.com/goplus/gop/cl/internal/typesutil" "github.com/goplus/gop/token" "github.com/goplus/gox" "github.com/goplus/gox/cpackages" @@ -220,7 +221,7 @@ type goxRecorder struct { // Member maps identifiers to the objects they denote. func (p *goxRecorder) Member(id ast.Node, obj types.Object) { - tv := types.TypeAndValue{Type: obj.Type()} + tv := typesutil.NewTypeAndValueForObject(obj) switch v := id.(type) { case *ast.SelectorExpr: sel := v.Sel diff --git a/cl/expr.go b/cl/expr.go index 00d90fe98..3752c6529 100644 --- a/cl/expr.go +++ b/cl/expr.go @@ -158,12 +158,11 @@ find: e := ctx.cb.Get(-1) if oldo != nil && gox.IsTypeEx(e.Type) { rec.Use(ident, oldo) + rec.Type(ident, typesutil.NewTypeAndValueForObject(oldo)) return } rec.Use(ident, o) - typ, _ := gox.DerefType(e.Type) - tv := typesutil.NewTypeAndValue(typ, e.CVal) - rec.Type(ident, tv) + rec.Type(ident, typesutil.NewTypeAndValueForObject(o)) } return } @@ -199,6 +198,7 @@ func compileExprLHS(ctx *blockCtx, expr ast.Expr) { compileIndexExprLHS(ctx, v) case *ast.SelectorExpr: compileSelectorExprLHS(ctx, v) + recordTypesVariable(ctx, v, -1) case *ast.StarExpr: compileStarExprLHS(ctx, v) default: @@ -210,6 +210,21 @@ func twoValue(inFlags []int) bool { return inFlags != nil && (inFlags[0]&clCallWithTwoValue) != 0 } +func recordTypesValue(ctx *blockCtx, expr ast.Expr, n int) { + if rec := ctx.recorder(); rec != nil { + e := ctx.cb.Get(n) + rec.Type(expr, typesutil.NewTypeAndValueForValue(e.Type, e.CVal)) + } +} + +func recordTypesVariable(ctx *blockCtx, expr ast.Expr, n int) { + if rec := ctx.recorder(); rec != nil { + e := ctx.cb.Get(n) + t, _ := gox.DerefType(e.Type) + rec.Type(expr, typesutil.NewTypeAndValueForVariable(t)) + } +} + func compileExpr(ctx *blockCtx, expr ast.Expr, inFlags ...int) { switch v := expr.(type) { case *ast.Ident: @@ -220,6 +235,7 @@ func compileExpr(ctx *blockCtx, expr ast.Expr, inFlags ...int) { compileIdent(ctx, v, flags) case *ast.BasicLit: compileBasicLit(ctx, v) + recordTypesValue(ctx, v, -1) case *ast.CallExpr: flags := 0 if inFlags != nil { @@ -234,8 +250,10 @@ func compileExpr(ctx *blockCtx, expr ast.Expr, inFlags ...int) { compileSelectorExpr(ctx, v, flags) case *ast.BinaryExpr: compileBinaryExpr(ctx, v) + recordTypesValue(ctx, v, -1) case *ast.UnaryExpr: compileUnaryExpr(ctx, v, twoValue(inFlags)) + recordTypesValue(ctx, v, -1) case *ast.FuncLit: compileFuncLit(ctx, v) case *ast.CompositeLit: @@ -359,10 +377,6 @@ func compileSelectorExprLHS(ctx *blockCtx, v *ast.SelectorExpr) { } default: compileExpr(ctx, v.X) - if rec := ctx.recorder(); rec != nil { - e := ctx.cb.Get(-1) - rec.Type(v.X, typesutil.NewTypeAndValue(e.Type, e.CVal)) - } } ctx.cb.MemberRef(v.Sel.Name, v) } @@ -383,7 +397,7 @@ func compileSelectorExpr(ctx *blockCtx, v *ast.SelectorExpr, flags int) { compileExpr(ctx, v.X) if rec := ctx.recorder(); rec != nil { e := ctx.cb.Get(-1) - rec.Type(v.X, typesutil.NewTypeAndValue(e.Type, e.CVal)) + rec.Type(v.X, typesutil.NewTypeAndValueForType(e.Type)) } } if err := compileMember(ctx, v, v.Sel.Name, flags); err != nil { @@ -544,6 +558,9 @@ func compileCallExpr(ctx *blockCtx, v *ast.CallExpr, inFlags int) { for fn != nil { err := compileCallArgs(fn, fnt, ctx, v, ellipsis, flags) if err == nil { + if rec := ctx.recorder(); rec != nil { + rec.Type(v, typesutil.NewTypeAndValueForCallResult(ctx.cb.Get(-1).Type)) + } break } if fn.next == nil { @@ -794,6 +811,9 @@ func compileStructLitInKeyVal(ctx *blockCtx, elts []ast.Expr, t *types.Struct, t err := ctx.newCodeErrorf(name.Pos(), "%s undefined (type %v has no field or method %s)", src, typ, name.Name) panic(err) } + if rec := ctx.recorder(); rec != nil { + rec.Use(name, t.Field(idx)) + } switch expr := kv.Value.(type) { case *ast.LambdaExpr, *ast.LambdaExpr2: sig := checkLambdaFuncType(ctx, expr, t.Field(idx).Type(), clLambaField, kv.Key) @@ -878,6 +898,9 @@ func compileCompositeLit(ctx *blockCtx, v *ast.CompositeLit, expected types.Type } if t, ok := underlying.(*types.Struct); ok && kind == compositeLitKeyVal { compileStructLitInKeyVal(ctx, v.Elts, t, typ, v) + if rec := ctx.recorder(); rec != nil { + rec.Type(v, typesutil.NewTypeAndValueForValue(typ, nil)) + } if hasPtr { ctx.cb.UnaryOp(gotoken.AND) } @@ -892,6 +915,10 @@ func compileCompositeLit(ctx *blockCtx, v *ast.CompositeLit, expected types.Type ctx.cb.MapLit(nil, n<<1) return } + if rec := ctx.recorder(); rec != nil { + rec.Type(v.Type, typesutil.NewTypeAndValueForType(typ)) + rec.Type(v, typesutil.NewTypeAndValueForValue(typ, nil)) + } switch underlying.(type) { case *types.Slice: ctx.cb.SliceLitEx(typ, n< Date: Thu, 16 Nov 2023 09:06:21 +0800 Subject: [PATCH 06/14] x --- x/typesutil/info_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x/typesutil/info_test.go b/x/typesutil/info_test.go index a5de26582..840ab8d21 100644 --- a/x/typesutil/info_test.go +++ b/x/typesutil/info_test.go @@ -83,8 +83,7 @@ func testInfo(t *testing.T, src interface{}) { if err != nil { t.Fatal("parserGoSource error", err) } - // TODO check types - //testItems(t, "types", typesList(fset, info.Types), goTypesList(fset, goinfo.Types)) + testItems(t, "types", typesList(fset, info.Types), goTypesList(fset, goinfo.Types)) testItems(t, "defs", defsList(fset, info.Defs, true), goDefsList(fset, goinfo.Defs, true)) testItems(t, "uses", usesList(fset, info.Uses), goUsesList(fset, goinfo.Uses)) // TODO check selections From deab96b50ba00cdaf8ea93589e4d88fb429bd29f Mon Sep 17 00:00:00 2001 From: visualfc Date: Sun, 19 Nov 2023 19:09:01 +0800 Subject: [PATCH 07/14] cl: commentFunc skip emtpy pos --- cl/stmt.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cl/stmt.go b/cl/stmt.go index b236c61ce..f0bb0cffe 100644 --- a/cl/stmt.go +++ b/cl/stmt.go @@ -58,8 +58,8 @@ func commentStmt(ctx *blockCtx, stmt ast.Stmt) { } func commentFunc(ctx *blockCtx, fn *gox.Func, decl *ast.FuncDecl) { - if ctx.fileLine { - start := decl.Name.Pos() + start := decl.Name.Pos() + if ctx.fileLine && start != token.NoPos { pos := ctx.fset.Position(start) if ctx.relativePath { pos.Filename = relFile(ctx.targetDir, pos.Filename) From 6ffddf6d2dec74b0d45dc7fca36c8f5244b1a5c7 Mon Sep 17 00:00:00 2001 From: visualfc Date: Mon, 20 Nov 2023 11:13:26 +0800 Subject: [PATCH 08/14] cl: fix compileIdent check class SelectorExpr --- cl/compile_spx_test.go | 25 ++++++++++++++++++++++++- cl/expr.go | 6 +++++- cl/internal/spx/pkg/pkg.go | 14 +++++++++----- cl/internal/spx/sprite.go | 9 +++++++++ 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/cl/compile_spx_test.go b/cl/compile_spx_test.go index 9d387a781..fd33712cf 100644 --- a/cl/compile_spx_test.go +++ b/cl/compile_spx_test.go @@ -698,10 +698,22 @@ func (this *Kai) onMsg(msg string) { func TestSpxPkgOverload(t *testing.T) { gopSpxTestEx(t, ` -println "Hi" +import "fmt" +fmt.println "Hi" `, ` func onMsg(msg string) { this.position.add 100,200 + position.add 100,200 + position.X += 100 + println position.X + this.vector.add 100,200 + vector.add 100,200 + vector.X += 100 + vector.self.X += 100 + vector.self.Y += 200 + vector.self.add position.X,position.Y + println vector.X + println vector.self.self } `, `package main @@ -728,6 +740,17 @@ type Kai struct { func (this *Kai) onMsg(msg string) { this.Position().Add__0(100, 200) + this.Position().Add__0(100, 200) + this.Position().X += 100 + fmt.Println(this.Position().X) + this.Vector().Add__0(100, 200) + this.Vector().Add__0(100, 200) + this.Vector().X += 100 + this.Vector().Self().X += 100 + this.Vector().Self().Y += 200 + this.Vector().Self().Add__0(this.Position().X, this.Position().Y) + fmt.Println(this.Vector().X) + fmt.Println(this.Vector().Self().Self()) } `, "Game.tgmx", "Kai.tspx") } diff --git a/cl/expr.go b/cl/expr.go index 3752c6529..b8dc8c845 100644 --- a/cl/expr.go +++ b/cl/expr.go @@ -100,7 +100,11 @@ func compileIdent(ctx *blockCtx, ident *ast.Ident, flags int) (pkg *gox.PkgRef, sig := fn.Ancestor().Type().(*types.Signature) if recv := sig.Recv(); recv != nil { ctx.cb.Val(recv) - if compileMember(ctx, ident, name, flags&^clCommandWithoutArgs) == nil { // class member object + chkFlag := flags &^ clCommandWithoutArgs + if chkFlag&clIdentSelectorExpr != 0 { + chkFlag = clIdentCanAutoCall + } + if compileMember(ctx, ident, name, chkFlag) == nil { // class member object return } ctx.cb.InternalStack().PopN(1) diff --git a/cl/internal/spx/pkg/pkg.go b/cl/internal/spx/pkg/pkg.go index 649406b52..9c77e7e70 100644 --- a/cl/internal/spx/pkg/pkg.go +++ b/cl/internal/spx/pkg/pkg.go @@ -5,8 +5,8 @@ var ( ) type Vector struct { - x int - y int + X int + Y int } func NewVector(x, y int) *Vector { @@ -14,10 +14,14 @@ func NewVector(x, y int) *Vector { } func (v *Vector) Add__0(x int, y int) { - v.x += x - v.y += y + v.X += x + v.Y += y } func (v *Vector) Add__1(o *Vector) { - v.Add__0(o.x, o.y) + v.Add__0(o.X, o.Y) +} + +func (v *Vector) Self() *Vector { + return v } diff --git a/cl/internal/spx/sprite.go b/cl/internal/spx/sprite.go index 00963bb87..b6b0615fb 100644 --- a/cl/internal/spx/sprite.go +++ b/cl/internal/spx/sprite.go @@ -22,6 +22,15 @@ import ( type Sprite struct { pos pkg.Vector + Entry +} + +type Entry struct { + vec pkg.Vector +} + +func (p *Entry) Vector() *pkg.Vector { + return &p.vec } func (p *Sprite) SetCostume(costume interface{}) { From 1de53d02079edcc8fe1a31528a6dca95e2038708 Mon Sep 17 00:00:00 2001 From: visualfc Date: Mon, 20 Nov 2023 12:31:19 +0800 Subject: [PATCH 09/14] cl: TestSpxSelection --- cl/compile_spx_test.go | 44 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/cl/compile_spx_test.go b/cl/compile_spx_test.go index fd33712cf..cbb010e78 100644 --- a/cl/compile_spx_test.go +++ b/cl/compile_spx_test.go @@ -698,11 +698,48 @@ func (this *Kai) onMsg(msg string) { func TestSpxPkgOverload(t *testing.T) { gopSpxTestEx(t, ` -import "fmt" -fmt.println "Hi" +println "Hi" `, ` func onMsg(msg string) { this.position.add 100,200 +} +`, `package main + +import ( + "fmt" + "github.com/goplus/gop/cl/internal/spx" +) + +type Game struct { + *spx.MyGame +} + +func (this *Game) MainEntry() { + fmt.Println("Hi") +} +func main() { + spx.Gopt_MyGame_Main(new(Game)) +} + +type Kai struct { + spx.Sprite + *Game +} + +func (this *Kai) onMsg(msg string) { + this.Position().Add__0(100, 200) +} +`, "Game.tgmx", "Kai.tspx") +} + +func TestSpxSelection(t *testing.T) { + gopSpxTestEx(t, ` +println "hi" +`, ` +import "fmt" +func onMsg(msg string) { + fmt.println msg + this.position.add 100,200 position.add 100,200 position.X += 100 println position.X @@ -727,7 +764,7 @@ type Game struct { } func (this *Game) MainEntry() { - fmt.Println("Hi") + fmt.Println("hi") } func main() { spx.Gopt_MyGame_Main(new(Game)) @@ -739,6 +776,7 @@ type Kai struct { } func (this *Kai) onMsg(msg string) { + fmt.Println(msg) this.Position().Add__0(100, 200) this.Position().Add__0(100, 200) this.Position().X += 100 From d6bf71e647d4b041ee9c6928bbd3f0981f2bf517 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Mon, 20 Nov 2023 21:52:14 +0800 Subject: [PATCH 10/14] gop clean -t --- cmd/internal/clean/clean.go | 48 ++++++++++++++++++++++++------------- gengo.go | 2 +- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/cmd/internal/clean/clean.go b/cmd/internal/clean/clean.go index 12d448eca..a06c5fcee 100644 --- a/cmd/internal/clean/clean.go +++ b/cmd/internal/clean/clean.go @@ -18,7 +18,6 @@ package clean import ( "fmt" - "io/ioutil" "log" "os" "path/filepath" @@ -28,15 +27,15 @@ import ( ) const ( - autoGenFile = "gop_autogen.go" - autoGenTestFile = "gop_autogen_test.go" - autoGen2TestFile = "gop_autogen2_test.go" + autoGenFileSuffix = "_autogen.go" + autoGenTestFile = "gop_autogen_test.go" + autoGen2TestFile = "gop_autogen2_test.go" ) // ----------------------------------------------------------------------------- -func cleanAGFiles(dir string) { - fis, err := ioutil.ReadDir(dir) +func cleanAGFiles(dir string, execAct bool) { + fis, err := os.ReadDir(dir) if err != nil { return } @@ -48,25 +47,34 @@ func cleanAGFiles(dir string) { if fi.IsDir() { pkgDir := filepath.Join(dir, fname) if fname == ".gop" { - removeGopDir(pkgDir) + removeGopDir(pkgDir, execAct) } else { - cleanAGFiles(pkgDir) + cleanAGFiles(pkgDir, execAct) } continue } + if strings.HasSuffix(fname, autoGenFileSuffix) { + file := filepath.Join(dir, fname) + fmt.Printf("Cleaning %s ...\n", file) + if execAct { + os.Remove(file) + } + } } - autogens := []string{autoGenFile, autoGenTestFile, autoGen2TestFile} + autogens := []string{autoGenTestFile, autoGen2TestFile} for _, autogen := range autogens { file := filepath.Join(dir, autogen) if _, err = os.Stat(file); err == nil { fmt.Printf("Cleaning %s ...\n", file) - os.Remove(file) + if execAct { + os.Remove(file) + } } } } -func removeGopDir(dir string) { - fis, err := ioutil.ReadDir(dir) +func removeGopDir(dir string, execAct bool) { + fis, err := os.ReadDir(dir) if err != nil { return } @@ -75,23 +83,29 @@ func removeGopDir(dir string) { if strings.HasSuffix(fname, ".gop.go") { genfile := filepath.Join(dir, fname) fmt.Printf("Cleaning %s ...\n", genfile) - os.Remove(genfile) + if execAct { + os.Remove(genfile) + } } } - os.Remove(dir) + if execAct { + os.Remove(dir) + } } // ----------------------------------------------------------------------------- // Cmd - gop clean var Cmd = &base.Command{ - UsageLine: "gop clean [-v] ", + UsageLine: "gop clean [flags] ", Short: "Clean all Go+ auto generated files", } var ( flag = &Cmd.Flag - _ = flag.Bool("v", false, "print verbose information.") + + _ = flag.Bool("v", false, "print verbose information.") + testMode = flag.Bool("t", false, "test mode: display files to clean but don't clean them.") ) func init() { @@ -109,7 +123,7 @@ func runCmd(_ *base.Command, args []string) { } else { dir = flag.Arg(0) } - cleanAGFiles(dir) + cleanAGFiles(dir, !*testMode) } // ----------------------------------------------------------------------------- diff --git a/gengo.go b/gengo.go index 66eb0e23c..0e2337361 100644 --- a/gengo.go +++ b/gengo.go @@ -138,7 +138,7 @@ func genGoEntry(list *errors.List, path string, d fs.DirEntry, conf *Config, fla func genGoSingleFile(file string, conf *Config, flags GenFlags) (err error) { dir, fname := filepath.Split(file) - autogen := dir + strings.TrimSuffix(fname, ".gop") + "_augogen.go" + autogen := dir + strings.TrimSuffix(fname, ".gop") + "_autogen.go" if (flags & GenFlagPrompt) != 0 { fmt.Fprintln(os.Stderr, "GenGo", file, "...") } From b80a6c1d4c181a1655a517e7ef2dc02781454f93 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Mon, 20 Nov 2023 22:35:59 +0800 Subject: [PATCH 11/14] gocmd.Name: use env GOP_GOCMD --- cmd/internal/env/env.go | 2 ++ x/gocmd/gocmd.go | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/cmd/internal/env/env.go b/cmd/internal/env/env.go index 0fcb86a72..43febb859 100644 --- a/cmd/internal/env/env.go +++ b/cmd/internal/env/env.go @@ -27,6 +27,7 @@ import ( "github.com/goplus/gop/cmd/internal/base" "github.com/goplus/gop/env" + "github.com/goplus/gop/x/gocmd" "github.com/goplus/mod" "github.com/goplus/mod/modcache" ) @@ -71,6 +72,7 @@ func runCmd(_ *base.Command, args []string) { gopEnv["BUILDDATE"] = env.BuildDate() gopEnv["GOPVERSION"] = env.Version() gopEnv["GOPROOT"] = env.GOPROOT() + gopEnv["GOP_GOCMD"] = gocmd.Name() gopEnv["GOMODCACHE"] = modcache.GOMODCACHE gopEnv["GOPMOD"], _ = mod.GOPMOD("", 0) gopEnv["HOME"] = env.HOME() diff --git a/x/gocmd/gocmd.go b/x/gocmd/gocmd.go index ffb894666..30a8b14ed 100644 --- a/x/gocmd/gocmd.go +++ b/x/gocmd/gocmd.go @@ -29,6 +29,7 @@ type GopEnv = env.Gop type Config struct { Gop *GopEnv + GoCmd string Flags []string Run func(cmd *exec.Cmd) error } @@ -39,12 +40,16 @@ func doWithArgs(op string, conf *Config, args ...string) (err error) { if conf == nil { conf = new(Config) } + goCmd := conf.GoCmd + if goCmd == "" { + goCmd = Name() + } exargs := make([]string, 1, 16) exargs[0] = op exargs = appendLdflags(exargs, conf.Gop) exargs = append(exargs, conf.Flags...) exargs = append(exargs, args...) - cmd := exec.Command("go", exargs...) + cmd := exec.Command(goCmd, exargs...) run := conf.Run if run == nil { run = runCmd @@ -83,3 +88,16 @@ func appendLdflags(exargs []string, env *GopEnv) []string { } // ----------------------------------------------------------------------------- + +// Name returns name of the go command. +// It returns value of environment variable `GOP_GOCMD` if not empty. +// If not found, it returns `go`. +func Name() string { + goCmd := os.Getenv("GOP_GOCMD") + if goCmd == "" { + goCmd = "go" + } + return goCmd +} + +// ----------------------------------------------------------------------------- From b226db4716927a4de50c001009fbec53825d620c Mon Sep 17 00:00:00 2001 From: visualfc Date: Wed, 22 Nov 2023 11:29:33 +0800 Subject: [PATCH 12/14] cl: config add option FileLineRoot for comment line --- cl/compile.go | 11 ++++++++++ cl/compile_test.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++ cl/stmt.go | 18 ++++++++++++++-- load.go | 11 +++++----- 4 files changed, 87 insertions(+), 7 deletions(-) diff --git a/cl/compile.go b/cl/compile.go index d6d64bba0..248377275 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/compile_test.go b/cl/compile_test.go index e058472a7..b6bb9c651 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -4652,3 +4652,57 @@ func main() { } `) } + +func TestCommentLineRoot(t *testing.T) { + conf := *gblConf + conf.NoFileLine = false + conf.FileLineRoot = "/root" + gopClTestEx(t, &conf, "main", ` +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() +`, `package main + +import "fmt" + +type Point struct { + x int + y int +} +//line ../foo/bar.gop:7:1 +func (pt *Point) Test() { +//line ../foo/bar.gop:8:1 + fmt.Println(pt.x, pt.y) +} +// testPoint is test point +// +//line ../foo/bar.gop:12:1 +func testPoint() { +//line ../foo/bar.gop:13:1 + var pt Point +//line ../foo/bar.gop:14:1 + pt.Test() +} +//line ../foo/bar.gop:17 +func main() { +//line ../foo/bar.gop:17:1 + fmt.Println("hello") +//line ../foo/bar.gop:18:1 + testPoint() +} +`) +} diff --git a/cl/stmt.go b/cl/stmt.go index f0bb0cffe..805646b5a 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 a26bad87e..3e8ae230b 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") { From 320ff4114358e1a31f70922fdf367866eea2aa56 Mon Sep 17 00:00:00 2001 From: visualfc Date: Wed, 22 Nov 2023 13:44:14 +0800 Subject: [PATCH 13/14] x --- cl/compile_test.go | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/cl/compile_test.go b/cl/compile_test.go index b6bb9c651..52022aebf 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" @@ -4656,8 +4657,10 @@ func main() { func TestCommentLineRoot(t *testing.T) { conf := *gblConf conf.NoFileLine = false - conf.FileLineRoot = "/root" - gopClTestEx(t, &conf, "main", ` + conf.FileLineRoot = "/foo/root" + conf.WorkingDir = "/foo" + conf.TargetDir = "/foo" + var src = ` type Point struct { x int y int @@ -4675,7 +4678,8 @@ func testPoint() { println "hello" testPoint() -`, `package main +` + var expected = `package main import "fmt" @@ -4683,26 +4687,30 @@ type Point struct { x int y int } -//line ../foo/bar.gop:7:1 +//line ../bar.gop:7:1 func (pt *Point) Test() { -//line ../foo/bar.gop:8:1 +//line ../bar.gop:8:1 fmt.Println(pt.x, pt.y) } // testPoint is test point // -//line ../foo/bar.gop:12:1 +//line ../bar.gop:12:1 func testPoint() { -//line ../foo/bar.gop:13:1 +//line ../bar.gop:13:1 var pt Point -//line ../foo/bar.gop:14:1 +//line ../bar.gop:14:1 pt.Test() } -//line ../foo/bar.gop:17 +//line ../bar.gop:17 func main() { -//line ../foo/bar.gop:17:1 +//line ../bar.gop:17:1 fmt.Println("hello") -//line ../foo/bar.gop:18:1 +//line ../bar.gop:18:1 testPoint() } -`) +` + if runtime.GOOS == "windows" { + expected = strings.Replace(expected, "../", `..\foo\`, -1) + } + gopClTestEx(t, &conf, "main", src, expected) } From bcc2f90bc816dc44ee592f814afaa8b6b5ae320d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 25 Nov 2023 02:42:55 +0000 Subject: [PATCH 14/14] build(deps): bump github.com/goplus/c2go from 0.7.17 to 0.7.18 Bumps [github.com/goplus/c2go](https://github.com/goplus/c2go) from 0.7.17 to 0.7.18. - [Release notes](https://github.com/goplus/c2go/releases) - [Commits](https://github.com/goplus/c2go/compare/v0.7.17...v0.7.18) --- updated-dependencies: - dependency-name: github.com/goplus/c2go dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 20 +++++++++----------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index 991808f3e..07ae18135 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,8 @@ go 1.18 require ( github.com/fsnotify/fsnotify v1.7.0 - github.com/goplus/c2go v0.7.17 - github.com/goplus/gox v1.13.0 + github.com/goplus/c2go v0.7.18 + github.com/goplus/gox v1.13.1 github.com/goplus/mod v0.11.9 github.com/qiniu/x v1.13.1 golang.org/x/tools v0.15.0 diff --git a/go.sum b/go.sum index a09aa0885..c9d92aff1 100644 --- a/go.sum +++ b/go.sum @@ -4,10 +4,10 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/goplus/c2go v0.7.17 h1:q/b0Fv1ggJUo0E0ZN/3t8zoE9vmJYTDtAlNSzedeCAA= -github.com/goplus/c2go v0.7.17/go.mod h1:HhlHE5OAwrJyjg3Dz6yj3b1drugJdoUiWeUl+G3NnU4= -github.com/goplus/gox v1.13.0 h1:QtgYiZs3J1cFqu4yVZPqOnbbXHk6vDqLNkG4DUIg4EY= -github.com/goplus/gox v1.13.0/go.mod h1:MOJnwqA8/rSUkn0vsayHFK7TD/3XQrdexMTqdzR70X0= +github.com/goplus/c2go v0.7.18 h1:lymExgcOTTfMSe8eGlZm3LntBmueDpgNEQQsnLlY3qg= +github.com/goplus/c2go v0.7.18/go.mod h1:XZJUGrDT0uD0a7clRNRJF8gAi1zfHfFbA8UVIlPqz2w= +github.com/goplus/gox v1.13.1 h1:/X6Ja9R2hQuLVbN+PzLHRtaBcan+YmhASvGO3nMJsZw= +github.com/goplus/gox v1.13.1/go.mod h1:UNzOPlRyO/uQn+9iHelk6KelAFaaC7OBn5AxtSSsC9c= github.com/goplus/mod v0.11.9 h1:XdWvSNi55fQ3KHnk0PVVHsXynG58lTbfXps/C9HjTVQ= github.com/goplus/mod v0.11.9/go.mod h1:YxrBMhvWGcvLU14j8e7qyKSVnj5Loba7GgH1rNXJtDg= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -27,11 +27,10 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -40,13 +39,13 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -55,7 +54,6 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -63,19 +61,19 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=