Repository: goplus/gop
Pull request #1199 (2022-05-19 14:52:30)

goptestgo fix


Patch:
diff --git a/cl/compile.go b/cl/compile.go
index 466d3fce..58fee873 100644
--- a/cl/compile.go
+++ b/cl/compile.go
@@ -31,6 +31,7 @@ import (
 	"github.com/goplus/gop/ast/fromgo"
 	"github.com/goplus/gop/token"
 	"github.com/goplus/gox"
+	"github.com/goplus/gox/packages"
 	"github.com/goplus/mod/modfile"
 )
 
@@ -372,12 +373,17 @@ func NewPackage(pkgPath string, pkg *ast.Package, conf *Config) (p *gox.Package,
 	if targetDir == "" {
 		targetDir = workingDir
 	}
+	fset := conf.Fset
+	imp := conf.Importer
+	if imp == nil {
+		imp = packages.NewImporter(fset, workingDir)
+	}
 	files := pkg.Files
-	interp := &nodeInterp{fset: conf.Fset, files: files, workingDir: workingDir}
+	interp := &nodeInterp{fset: fset, files: files, workingDir: workingDir}
 	ctx := &pkgCtx{syms: make(map[string]loader), nodeInterp: interp}
 	confGox := &gox.Config{
-		Fset:            conf.Fset,
-		Importer:        newGopImporter(conf.GopRoot, conf.Importer),
+		Fset:            fset,
+		Importer:        newGopImporter(conf.GopRoot, imp),
 		LoadNamed:       ctx.loadNamed,
 		HandleErr:       ctx.handleErr,
 		NodeInterpreter: interp,
diff --git a/cl/func_type_and_var.go b/cl/func_type_and_var.go
index 632fadd0..df83facd 100644
--- a/cl/func_type_and_var.go
+++ b/cl/func_type_and_var.go
@@ -230,6 +230,9 @@ func toStructType(ctx *blockCtx, v *ast.StructType) *types.Struct {
 			if chkRedecl(name, field.Type.Pos()) {
 				continue
 			}
+			if t, ok := typ.(*types.Named); ok { // #1196: embedded type should ensure loaded
+				ctx.loadNamed(ctx.pkg, t)
+			}
 			fld := types.NewField(token.NoPos, pkg, name, typ, true)
 			fields = append(fields, fld)
 			tags = append(tags, toFieldTag(field.Tag))
@@ -316,7 +319,11 @@ func toInterfaceType(ctx *blockCtx, v *ast.InterfaceType) types.Type {
 	var embeddeds []types.Type
 	for _, m := range methodsList {
 		if m.Names == nil { // embedded
-			embeddeds = append(embeddeds, toType(ctx, m.Type))
+			typ := toType(ctx, m.Type)
+			if t, ok := typ.(*types.Named); ok { // #1198: embedded type should ensure loaded
+				ctx.loadNamed(ctx.pkg, t)
+			}
+			embeddeds = append(embeddeds, typ)
 			continue
 		}
 		name := m.Names[0].Name
diff --git a/cl/stmt.go b/cl/stmt.go
index f83a339e..5f37927d 100644
--- a/cl/stmt.go
+++ b/cl/stmt.go
@@ -728,6 +728,9 @@ func compileDeclStmt(ctx *blockCtx, expr *ast.DeclStmt) {
 
 func compileType(ctx *blockCtx, t *ast.TypeSpec) {
 	name := t.Name.Name
+	if name == "_" {
+		return
+	}
 	if t.Assign != token.NoPos { // alias type
 		ctx.cb.AliasType(name, toType(ctx, t.Type))
 	} else {
diff --git a/go.mod b/go.mod
index c093ea94..992deeef 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/goplus/gop
 go 1.16
 
 require (
-	github.com/goplus/gox v1.11.5
+	github.com/goplus/gox v1.11.6
 	github.com/goplus/mod v0.9.3
 	github.com/qiniu/x v1.11.5
 )
diff --git a/go.sum b/go.sum
index bfe9bfa3..ee355176 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,5 @@
-github.com/goplus/gox v1.11.5 h1:/RL4L0f42b55/8RVeuYkOCNEPvfvyaT1dXfzmLUFYKo=
-github.com/goplus/gox v1.11.5/go.mod h1:gu7fuQF8RmWPZUjd+tEJGuV3m/vOEv0bHrct0x/KatM=
+github.com/goplus/gox v1.11.6 h1:gCJmuuZz0QIW2c5zT+yCItis9npc5Ud/WQydOYU3XXw=
+github.com/goplus/gox v1.11.6/go.mod h1:gu7fuQF8RmWPZUjd+tEJGuV3m/vOEv0bHrct0x/KatM=
 github.com/goplus/mod v0.9.3 h1:kXN2kavdUacqy39Lh/pIdT0zvBTKevb4u96ZbapPbcg=
 github.com/goplus/mod v0.9.3/go.mod h1:NHU13OjeNV3ez1f+R9FLJIlIun0KNSuZb0jnmP3N3o8=
 github.com/qiniu/x v1.11.5 h1:TYr5cl4g2yoHAZeDK4MTjKF6CMoG+IHlCDvvM5qym6U=
diff --git a/load.go b/load.go
index a9b4510b..93bc61fd 100644
--- a/load.go
+++ b/load.go
@@ -29,7 +29,6 @@ import (
 	"github.com/goplus/gop/parser"
 	"github.com/goplus/gop/x/gopenv"
 	"github.com/goplus/gox"
-	"github.com/goplus/gox/packages"
 	"github.com/goplus/mod/env"
 	"github.com/goplus/mod/gopmod"
 )
@@ -58,10 +57,6 @@ func LoadDir(dir string, conf *Config) (out, test *gox.Package, err error) {
 	if gop == nil {
 		gop = gopenv.Get()
 	}
-	imp := conf.Importer
-	if imp == nil {
-		imp = packages.NewImporter(fset, dir)
-	}
 
 	mod, err := gopmod.Load(dir, gop)
 	if err != nil && err != syscall.ENOENT {
@@ -96,7 +91,7 @@ func LoadDir(dir string, conf *Config) (out, test *gox.Package, err error) {
 		WorkingDir:  dir,
 		GopRoot:     gop.Root,
 		Fset:        fset,
-		Importer:    imp,
+		Importer:    conf.Importer,
 		LookupClass: mod.LookupClass,
 	}
 	for name, pkg := range pkgs {
@@ -137,6 +132,10 @@ func LoadFiles(files []string, conf *Config) (out *gox.Package, err error) {
 	if fset == nil {
 		fset = token.NewFileSet()
 	}
+	gop := conf.Gop
+	if gop == nil {
+		gop = gopenv.Get()
+	}
 
 	pkgs, err := parser.ParseFiles(fset, files, parser.ParseComments)
 	if err != nil {
@@ -147,6 +146,7 @@ func LoadFiles(files []string, conf *Config) (out *gox.Package, err error) {
 	}
 	for _, pkg := range pkgs {
 		out, err = cl.NewPackage("", pkg, &cl.Config{
+			GopRoot:  gop.Root,
 			Fset:     fset,
 			Importer: conf.Importer,
 		})


Test patch:
diff --git a/cl/compile_spx_test.go b/cl/compile_spx_test.go
index 24ffa55d..53435033 100644
--- a/cl/compile_spx_test.go
+++ b/cl/compile_spx_test.go
@@ -403,6 +403,7 @@ func (this *Kai) onMsg(msg string) {
 
 func TestSpxMainEntry(t *testing.T) {
 	conf := *gblConf
+	conf.Importer = nil
 	conf.NoAutoGenMain = false
 
 	gopSpxTestExConf(t, "Nocode", &conf, `
diff --git a/cl/compile_test.go b/cl/compile_test.go
index f6fbceab..86c3ab75 100644
--- a/cl/compile_test.go
+++ b/cl/compile_test.go
@@ -143,6 +143,176 @@ var x string = c.Str()
 `)
 }
 
+func TestUnderscoreRedeclared_Issue1197(t *testing.T) {
+	gopClTest(t, `
+func() (_ [2]int) { type _ int; return }()
+`, `package main
+
+func main() {
+	func() (_ [2]int) {
+		return
+	}()
+}
+`)
+}
+
+func TestInterfaceBugNilUnderlying_Issue1198(t *testing.T) {
+	gopClTest(t, `
+import "runtime"
+
+type Outer interface{ Inner }
+
+type impl struct{}
+
+func New() Outer { return &impl{} }
+
+type Inner interface {
+	DoStuff() error
+}
+
+func (a *impl) DoStuff() error {
+	return nil
+}
+
+func main() {
+	var outer Outer = New()
+}
+`, `package main
+
+type Inner interface {
+	DoStuff() error
+}
+type Outer interface {
+	Inner
+}
+type impl struct {
+}
+
+func (a *impl) DoStuff() error {
+	return nil
+}
+func New() Outer {
+	return &impl{}
+}
+func main() {
+	var outer Outer = New()
+}
+`)
+}
+
+func TestInterfaceBugNilUnderlying_Issue1196(t *testing.T) {
+	gopClTest(t, `
+func main() {
+	i := I(A{})
+
+	b := make(chan I, 1)
+	b <- B{}
+
+	var ok bool
+	i, ok = <-b
+}
+
+type I interface{ M() int }
+
+type T int
+
+func (T) M() int { return 0 }
+
+type A struct{ T }
+type B struct{ T }
+`, `package main
+
+func main() {
+	i := I(A{})
+	b := make(chan I, 1)
+	b <- B{}
+	var ok bool
+	i, ok = <-b
+}
+
+type T int
+
+func (T) M() int {
+	return 0
+}
+
+type A struct {
+	T
+}
+type I interface {
+	M() int
+}
+type B struct {
+	T
+}
+`)
+}
+
+func TestMyIntInc_Issue1195(t *testing.T) {
+	gopClTest(t, `
+type MyInt int
+var c MyInt
+c++
+`, `package main
+
+type MyInt int
+
+var c MyInt
+
+func main() {
+	c++
+}
+`)
+}
+
+func TestAutoPropMixedName_Issue1194(t *testing.T) {
+	gopClTest(t, `
+type Point struct {
+	Min, Max int
+}
+
+type Obj struct {
+	bbox Point
+}
+
+func (o *Obj) Bbox() Point {
+	return o.bbox
+}
+
+func (o *Obj) Points() [2]int{
+	return [2]int{o.bbox.Min, o.bbox.Max}
+}
+`, `package main
+
+type Point struct {
+	Min int
+	Max int
+}
+type Obj struct {
+	bbox Point
+}
+
+func (o *Obj) Bbox() Point {
+	return o.bbox
+}
+func (o *Obj) Points() [2]int {
+	return [2]int{o.bbox.Min, o.bbox.Max}
+}
+`)
+}
+
+func TestShiftUntypedInt_Issue1193(t *testing.T) {
+	gopClTest(t, `
+func GetValue(shift uint) uint {
+	return 1 << shift
+}`, `package main
+
+func GetValue(shift uint) uint {
+	return 1 << shift
+}
+`)
+}
+
 func TestInitFunc(t *testing.T) {
 	gopClTest(t, `
 
diff --git a/cmd/goptestgo/goptestgo.go b/cmd/goptestgo/goptestgo.go
index 979d857c..43f426e4 100644
--- a/cmd/goptestgo/goptestgo.go
+++ b/cmd/goptestgo/goptestgo.go
@@ -41,7 +41,7 @@ func fileIsDirty(srcMod time.Time, destFile string) bool {
 	return srcMod.After(fiDest.ModTime())
 }
 
-func runGoFile(dir, file string) {
+func runGoFile(dir, file, fname string) {
 	gopEnv := gopenv.Get()
 	conf := &gop.Config{Gop: gopEnv}
 	confCmd := &gocmd.BuildConfig{Gop: gopEnv}
@@ -51,7 +51,7 @@ func runGoFile(dir, file string) {
 	}
 	absFile, _ := filepath.Abs(file)
 	hash := sha1.Sum([]byte(absFile))
-	outFile := dir + "g" + base64.RawURLEncoding.EncodeToString(hash[:]) + ".go"
+	outFile := dir + "g" + base64.RawURLEncoding.EncodeToString(hash[:]) + fname
 	if fileIsDirty(fi.ModTime(), outFile) {
 		err = gop.RunFiles(outFile, []string{file}, nil, conf, confCmd)
 		if err != nil {
@@ -82,6 +82,8 @@ var (
 		"issue18149.go":     {},
 		"issue22662.go":     {},
 		"issue27201.go":     {},
+		"issue46903.go":     {},
+		"issue50190.go":     {}, // interesting, should be fixed
 		"nilptr_aix.go":     {},
 		"inline_literal.go": {},
 		"returntype.go":     {}, // not a problem
@@ -92,6 +94,7 @@ var (
 func gopTestRunGo(dir string) {
 	home, _ := os.UserHomeDir()
 	targetDir := home + "/.gop/run/"
+	os.MkdirAll(targetDir, 0777)
 	filepath.Walk(dir, func(file string, fi os.FileInfo, err error) error {
 		name := fi.Name()
 		if err != nil || fi.IsDir() {
@@ -115,7 +118,7 @@ func gopTestRunGo(dir string) {
 			return nil
 		}
 		log.Println("==> gop run -v", file)
-		runGoFile(targetDir, file)
+		runGoFile(targetDir, file, name)
 		return nil
 	})
 }