Repository: goplus/gop
Pull request #1225 (2022-05-30 14:17:27)

v1.1.0


Patch:
diff --git a/VERSION b/VERSION
deleted file mode 100644
index c8d512ba..00000000
--- a/VERSION
+++ /dev/null
@@ -1,1 +0,0 @@
-v1.1.0-rc2
diff --git a/build_install_run.go b/build_install_run.go
index 706ac959..089b7d00 100644
--- a/build_install_run.go
+++ b/build_install_run.go
@@ -27,7 +27,7 @@ import (
 // -----------------------------------------------------------------------------
 
 func InstallDir(dir string, conf *Config, install *gocmd.InstallConfig) (err error) {
-	_, _, err = GenGo(dir, conf)
+	_, _, err = GenGo(dir, conf, false)
 	if err != nil {
 		return
 	}
@@ -74,7 +74,7 @@ func chdir(dir string) string {
 // -----------------------------------------------------------------------------
 
 func BuildDir(dir string, conf *Config, build *gocmd.BuildConfig) (err error) {
-	_, _, err = GenGo(dir, conf)
+	_, _, err = GenGo(dir, conf, false)
 	if err != nil {
 		return
 	}
@@ -112,7 +112,7 @@ func restoreDirAndMod(old string) {
 // -----------------------------------------------------------------------------
 
 func RunDir(dir string, args []string, conf *Config, run *gocmd.RunConfig) (err error) {
-	_, _, err = GenGo(dir, conf)
+	_, _, err = GenGo(dir, conf, false)
 	if err != nil {
 		return
 	}
@@ -146,7 +146,7 @@ func RunFiles(autogen string, files []string, args []string, conf *Config, run *
 // -----------------------------------------------------------------------------
 
 func TestDir(dir string, conf *Config, test *gocmd.TestConfig) (err error) {
-	_, _, err = GenGo(dir, conf)
+	_, _, err = GenGo(dir, conf, true)
 	if err != nil {
 		return
 	}
diff --git a/cmd/internal/gengo/go.go b/cmd/internal/gengo/go.go
index ab361183..b84be5d0 100644
--- a/cmd/internal/gengo/go.go
+++ b/cmd/internal/gengo/go.go
@@ -69,7 +69,7 @@ func runCmd(cmd *base.Command, args []string) {
 	for _, proj := range projs {
 		switch v := proj.(type) {
 		case *gopprojs.DirProj:
-			_, _, err = gop.GenGo(v.Dir, nil)
+			_, _, err = gop.GenGo(v.Dir, nil, true)
 		case *gopprojs.PkgPathProj:
 			_, _, err = gop.GenGoPkgPath("", v.Path, nil, true)
 		default:
diff --git a/cmd/internal/mod/tidy.go b/cmd/internal/mod/tidy.go
index b7369999..615afe46 100644
--- a/cmd/internal/mod/tidy.go
+++ b/cmd/internal/mod/tidy.go
@@ -20,15 +20,11 @@ import (
 	"fmt"
 	"log"
 	"os"
-	"os/exec"
 	"syscall"
 
 	"github.com/goplus/gop"
 	"github.com/goplus/gop/cmd/internal/base"
 	"github.com/goplus/gop/x/gopenv"
-	"github.com/goplus/mod"
-	"github.com/goplus/mod/gopmod"
-	"github.com/goplus/mod/modfetch"
 )
 
 // gop mod tidy
@@ -42,7 +38,7 @@ func init() {
 }
 
 func runTidy(cmd *base.Command, args []string) {
-	mod, err := gopmod.Load(".", mod.GopModOnly)
+	err := gop.Tidy(".", gopenv.Get())
 	if err != nil {
 		if err == syscall.ENOENT {
 			fmt.Fprintln(os.Stderr, "gop.mod not found")
@@ -50,44 +46,4 @@ func runTidy(cmd *base.Command, args []string) {
 		}
 		log.Panicln(err)
 	}
-
-	depMods, err := gop.GenDepMods(mod, mod.Root(), true)
-	check(err)
-
-	tidy(mod, depMods)
-}
-
-func tidy(mod *gopmod.Module, depMods map[string]struct{}) {
-	old := mod.DepMods()
-	for modPath := range old {
-		if _, ok := depMods[modPath]; !ok { // removed
-			mod.DropRequire(modPath)
-		}
-	}
-	for modPath := range depMods {
-		if _, ok := old[modPath]; !ok { // added
-			if newMod, err := modfetch.Get(modPath); err != nil {
-				log.Fatalln(err)
-			} else {
-				mod.AddRequire(newMod.Path, newMod.Version)
-			}
-		}
-	}
-
-	err := mod.Save()
-	check(err)
-
-	_, _, err = gop.GenGo(mod.Root()+"/...", &gop.Config{DontUpdateGoMod: true})
-	check(err)
-
-	err = mod.UpdateGoMod(gopenv.Get(), true)
-	check(err)
-
-	cmd := exec.Command("go", "mod", "tidy")
-	cmd.Stdout = os.Stdout
-	cmd.Stderr = os.Stderr
-	cmd.Stdin = os.Stdin
-	cmd.Dir = mod.Root()
-	err = cmd.Run()
-	check(err)
 }
diff --git a/gendeps.go b/gendeps.go
index 9cc4fdc1..b4f1deb5 100644
--- a/gendeps.go
+++ b/gendeps.go
@@ -38,7 +38,7 @@ func GenDepMods(mod *gopmod.Module, dir string, recursively bool) (ret map[strin
 	ret = make(map[string]struct{})
 	err = HandleDeps(mod, dir, recursively, func(pkgPath string) {
 		modPath, _ := modfetch.Split(pkgPath, modBase)
-		if modPath != "" {
+		if modPath != "" && modPath != modBase {
 			ret[modPath] = struct{}{}
 		}
 	})
diff --git a/gengo.go b/gengo.go
index 3d58d741..badd25c3 100644
--- a/gengo.go
+++ b/gengo.go
@@ -38,22 +38,22 @@ const (
 
 // -----------------------------------------------------------------------------
 
-func GenGo(dir string, conf *Config) (string, bool, error) {
+func GenGo(dir string, conf *Config, genTestPkg bool) (string, bool, error) {
 	recursively := strings.HasSuffix(dir, "/...")
 	if recursively {
 		dir = dir[:len(dir)-4]
 	}
-	return dir, recursively, genGoDir(dir, conf, recursively)
+	return dir, recursively, genGoDir(dir, conf, genTestPkg, recursively)
 }
 
-func genGoDir(dir string, conf *Config, recursively bool) (err error) {
+func genGoDir(dir string, conf *Config, genTestPkg, recursively bool) (err error) {
 	if recursively {
 		return filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
 			if err == nil && d.IsDir() {
 				if strings.HasPrefix(d.Name(), "_") { // skip _
 					return filepath.SkipDir
 				}
-				err = genGoIn(path, conf, true)
+				err = genGoIn(path, conf, genTestPkg, true)
 				if err != nil {
 					fmt.Fprintln(os.Stderr, err)
 				}
@@ -61,11 +61,11 @@ func genGoDir(dir string, conf *Config, recursively bool) (err error) {
 			return err
 		})
 	}
-	return genGoIn(dir, conf, false)
+	return genGoIn(dir, conf, genTestPkg, false)
 }
 
-func genGoIn(dir string, conf *Config, prompt bool) (err error) {
-	out, test, err := LoadDir(dir, conf)
+func genGoIn(dir string, conf *Config, genTestPkg, prompt bool) (err error) {
+	out, test, err := LoadDir(dir, conf, genTestPkg)
 	if err != nil {
 		if err == syscall.ENOENT { // no Go+ source files
 			return nil
@@ -99,6 +99,11 @@ func genGoIn(dir string, conf *Config, prompt bool) (err error) {
 
 // -----------------------------------------------------------------------------
 
+const (
+	modWritable = 0755
+	modReadonly = 0555
+)
+
 func GenGoPkgPath(workDir, pkgPath string, conf *Config, allowExtern bool) (localDir string, recursively bool, err error) {
 	recursively = strings.HasSuffix(pkgPath, "/...")
 	if recursively {
@@ -108,10 +113,10 @@ func GenGoPkgPath(workDir, pkgPath string, conf *Config, allowExtern bool) (loca
 	mod, err := gopmod.Load(workDir, 0)
 	if err == syscall.ENOENT && allowExtern {
 		remotePkgPathDo(pkgPath, func(dir string) {
-			os.Chmod(dir, 0755)
-			defer os.Chmod(dir, 0555)
+			os.Chmod(dir, modWritable)
+			defer os.Chmod(dir, modReadonly)
 			localDir = dir
-			err = genGoDir(dir, conf, recursively)
+			err = genGoDir(dir, conf, false, recursively)
 		}, func(e error) {
 			err = e
 		})
@@ -126,10 +131,10 @@ func GenGoPkgPath(workDir, pkgPath string, conf *Config, allowExtern bool) (loca
 	}
 	localDir = pkg.Dir
 	if pkg.Type == gopmod.PkgtExtern {
-		os.Chmod(localDir, 0755)
-		defer os.Chmod(localDir, 0555)
+		os.Chmod(localDir, modWritable)
+		defer os.Chmod(localDir, modReadonly)
 	}
-	err = genGoDir(localDir, conf, recursively)
+	err = genGoDir(localDir, conf, false, recursively)
 	return
 }
 
diff --git a/go.mod b/go.mod
index f0ce156c..21a5e3bf 100644
--- a/go.mod
+++ b/go.mod
@@ -3,9 +3,9 @@ module github.com/goplus/gop
 go 1.16
 
 require (
-	github.com/goplus/c2go v0.7.2
+	github.com/goplus/c2go v0.7.5
 	github.com/goplus/gox v1.11.7
-	github.com/goplus/libc v0.3.6
-	github.com/goplus/mod v0.9.7
+	github.com/goplus/libc v0.3.7
+	github.com/goplus/mod v0.9.9
 	github.com/qiniu/x v1.11.5
 )
diff --git a/go.sum b/go.sum
index 39c12443..d6942864 100644
--- a/go.sum
+++ b/go.sum
@@ -2,14 +2,14 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/goplus/c2go v0.7.2 h1:jK4tD99Nej0PjPjBRZRahTftDPue5P+csylca/XjsMo=
-github.com/goplus/c2go v0.7.2/go.mod h1:Gd/r7JdrxXDoFKXyP6tsKTM0+j50CGxT0QDJ/5k8hYU=
+github.com/goplus/c2go v0.7.5 h1:lZHvPQUbGvT8jLbxI3gtU+83bjnHYagBsokkTK73DxE=
+github.com/goplus/c2go v0.7.5/go.mod h1:4KzA8rh0NkBk2MKKfZHaMyvIye8wxv99zXl32Kgc0Uc=
 github.com/goplus/gox v1.11.7 h1:YbTrET69TPdZFwT7ESKeDmwq7wpXRb3DUZ474bCC9Og=
 github.com/goplus/gox v1.11.7/go.mod h1:gu7fuQF8RmWPZUjd+tEJGuV3m/vOEv0bHrct0x/KatM=
-github.com/goplus/libc v0.3.6 h1:yqSe2179WwWyETo8vsqxwAgUL4EgjNVjPt68Pk6G/4U=
-github.com/goplus/libc v0.3.6/go.mod h1:nyKm7Iir6iI6hQT5WWUG6Jomx2zt/XRAGLLKtLrlICI=
-github.com/goplus/mod v0.9.7 h1:dH1XuDlMTkbWgEP1V4Mpz834W5NGwnfGQZ7tSpR5HXU=
-github.com/goplus/mod v0.9.7/go.mod h1:NHU13OjeNV3ez1f+R9FLJIlIun0KNSuZb0jnmP3N3o8=
+github.com/goplus/libc v0.3.7 h1:17CB0WBlnhXRjq+sKL3dy8scZrrHJEHyRXI2JTMDpqg=
+github.com/goplus/libc v0.3.7/go.mod h1:+3/Je2FnZ3aP6aX4vR79So07Yfy9Sv6r2JvdOXYPneA=
+github.com/goplus/mod v0.9.9 h1:EvXTp4Yb7jQ2q660jA74snVaQfLKyizHcZHicqjv/oU=
+github.com/goplus/mod v0.9.9/go.mod h1:NHU13OjeNV3ez1f+R9FLJIlIun0KNSuZb0jnmP3N3o8=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
 github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
diff --git a/imp.go b/imp.go
index 3111a613..059b2eb2 100644
--- a/imp.go
+++ b/imp.go
@@ -19,9 +19,12 @@ package gop
 import (
 	"go/token"
 	"go/types"
+	"os"
+	"path/filepath"
 	"strings"
 
 	"github.com/goplus/gox/packages"
+	"github.com/goplus/mod/env"
 	"github.com/goplus/mod/gopmod"
 	"github.com/goplus/mod/modfetch"
 )
@@ -31,16 +34,17 @@ import (
 type Importer struct {
 	impFrom *packages.Importer
 	mod     *gopmod.Module
-	gopRoot string
+	gop     *env.Gop
+	fset    *token.FileSet
 }
 
-func NewImporter(mod *gopmod.Module, fset *token.FileSet, gopRoot string) *Importer {
+func NewImporter(mod *gopmod.Module, gop *env.Gop, fset *token.FileSet) *Importer {
 	dir := ""
 	if mod.IsValid() {
 		dir = mod.Root()
 	}
 	impFrom := packages.NewImporter(fset, dir)
-	return &Importer{mod: mod, gopRoot: gopRoot, impFrom: impFrom}
+	return &Importer{mod: mod, gop: gop, impFrom: impFrom, fset: fset}
 }
 
 func (p *Importer) Import(pkgPath string) (pkg *types.Package, err error) {
@@ -49,24 +53,54 @@ func (p *Importer) Import(pkgPath string) (pkg *types.Package, err error) {
 	)
 	if strings.HasPrefix(pkgPath, gop) {
 		if suffix := pkgPath[len(gop):]; suffix == "" || suffix[0] == '/' {
-			return p.impFrom.ImportFrom(pkgPath, p.gopRoot, 0)
+			gopRoot := p.gop.Root
+			if suffix == "/cl/internal/gop-in-go/foo" {
+				if err = p.genGoExtern(gopRoot+suffix, false); err != nil {
+					return
+				}
+			}
+			return p.impFrom.ImportFrom(pkgPath, gopRoot, 0)
 		}
 	}
 	if mod := p.mod; mod.IsValid() {
-		if mod.PkgType(pkgPath) == gopmod.PkgtExtern {
-			ret, modVer, e := mod.LookupExternPkg(pkgPath)
-			if e != nil {
-				return nil, e
+		ret, e := mod.Lookup(pkgPath)
+		if e != nil {
+			return nil, e
+		}
+		switch ret.Type {
+		case gopmod.PkgtExtern:
+			isExtern := ret.Real.Version != ""
+			if isExtern {
+				if _, err = modfetch.Get(ret.Real.String()); err != nil {
+					return
+				}
 			}
-			if modVer.Version != "" {
-				if _, err = modfetch.Get(modVer.String()); err != nil {
+			modfile := filepath.Join(ret.ModDir, "gop.mod")
+			if _, e := os.Lstat(modfile); e == nil { // has gop.mod
+				if err = p.genGoExtern(ret.Dir, isExtern); err != nil {
 					return
 				}
 			}
-			return p.impFrom.ImportFrom(pkgPath, ret.Dir, 0)
+			return p.impFrom.ImportFrom(pkgPath, ret.ModDir, 0)
+		case gopmod.PkgtModule, gopmod.PkgtLocal:
+			if err = p.genGoExtern(ret.Dir, false); err != nil {
+				return
+			}
 		}
 	}
 	return p.impFrom.Import(pkgPath)
 }
 
+func (p *Importer) genGoExtern(dir string, isExtern bool) (err error) {
+	genfile := filepath.Join(dir, autoGenFile)
+	if _, err = os.Lstat(genfile); err == nil { // has gop_autogen.go
+		return
+	}
+	if isExtern {
+		os.Chmod(dir, modWritable)
+		defer os.Chmod(dir, modReadonly)
+	}
+	return genGoIn(dir, &Config{Gop: p.gop, Importer: p, Fset: p.fset}, false, false)
+}
+
 // -----------------------------------------------------------------------------
diff --git a/load.go b/load.go
index e37221ee..88ab6df9 100644
--- a/load.go
+++ b/load.go
@@ -19,6 +19,7 @@ package gop
 import (
 	"errors"
 	"go/token"
+	"go/types"
 	"io/fs"
 	"path/filepath"
 	"strings"
@@ -34,9 +35,10 @@ import (
 )
 
 type Config struct {
-	Gop    *env.Gop
-	Fset   *token.FileSet
-	Filter func(fs.FileInfo) bool
+	Gop      *env.Gop
+	Fset     *token.FileSet
+	Filter   func(fs.FileInfo) bool
+	Importer types.Importer
 
 	DontUpdateGoMod     bool
 	DontCheckModChanged bool
@@ -77,7 +79,7 @@ func lookupPub(mod *gopmod.Module) func(pkgPath string) (pubfile string, err err
 
 // -----------------------------------------------------------------------------
 
-func LoadDir(dir string, conf *Config) (out, test *gox.Package, err error) {
+func LoadDir(dir string, conf *Config, genTestPkg bool) (out, test *gox.Package, err error) {
 	if conf == nil {
 		conf = new(Config)
 	}
@@ -103,11 +105,16 @@ func LoadDir(dir string, conf *Config) (out, test *gox.Package, err error) {
 		return
 	}
 
+	imp := conf.Importer
+	if imp == nil {
+		imp = NewImporter(mod, gop, fset)
+	}
+
 	var pkgTest *ast.Package
 	var clConf = &cl.Config{
 		WorkingDir:  dir,
 		Fset:        fset,
-		Importer:    NewImporter(mod, fset, gop.Root),
+		Importer:    imp,
 		LookupClass: mod.LookupClass,
 		LookupPub:   lookupPub(mod),
 	}
@@ -133,7 +140,7 @@ func LoadDir(dir string, conf *Config) (out, test *gox.Package, err error) {
 	if out == nil {
 		return nil, nil, syscall.ENOENT
 	}
-	if pkgTest != nil {
+	if pkgTest != nil && genTestPkg {
 		test, err = cl.NewPackage("", pkgTest, clConf)
 	}
 	return
@@ -166,9 +173,13 @@ func LoadFiles(files []string, conf *Config) (out *gox.Package, err error) {
 		return nil, errMultiPackges
 	}
 	for _, pkg := range pkgs {
+		imp := conf.Importer
+		if imp == nil {
+			imp = NewImporter(mod, gop, fset)
+		}
 		out, err = cl.NewPackage("", pkg, &cl.Config{
 			Fset:        fset,
-			Importer:    NewImporter(mod, fset, gop.Root),
+			Importer:    imp,
 			LookupClass: mod.LookupClass,
 			LookupPub:   lookupPub(mod),
 		})
diff --git a/tidy.go b/tidy.go
new file mode 100644
index 00000000..826ef003
--- /dev/null
+++ b/tidy.go
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2021 The GoPlus Authors (goplus.org). All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package gop
+
+import (
+	"os"
+	"os/exec"
+
+	"github.com/goplus/mod"
+	"github.com/goplus/mod/env"
+	"github.com/goplus/mod/gopmod"
+	"github.com/goplus/mod/modfetch"
+)
+
+func Tidy(dir string, gop *env.Gop) (err error) {
+	mod, err := gopmod.Load(dir, mod.GopModOnly)
+	if err != nil {
+		return
+	}
+
+	modRoot := mod.Root()
+	depMods, err := GenDepMods(mod, modRoot, true)
+	if err != nil {
+		return
+	}
+
+	old := mod.DepMods()
+	for modPath := range old {
+		if _, ok := depMods[modPath]; !ok { // removed
+			mod.DropRequire(modPath)
+		}
+	}
+	for modPath := range depMods {
+		if _, ok := old[modPath]; !ok { // added
+			if newMod, e := modfetch.Get(modPath); e != nil {
+				return e
+			} else {
+				mod.AddRequire(newMod.Path, newMod.Version)
+			}
+		}
+	}
+
+	mod.Cleanup()
+	err = mod.Save()
+	if err != nil {
+		return
+	}
+
+	err = genGoDir(modRoot, &Config{DontUpdateGoMod: true, Gop: gop}, true, true)
+	if err != nil {
+		return
+	}
+
+	err = mod.UpdateGoMod(gop, true)
+	if err != nil {
+		return
+	}
+
+	cmd := exec.Command("go", "mod", "tidy")
+	cmd.Stdout = os.Stdout
+	cmd.Stderr = os.Stderr
+	cmd.Stdin = os.Stdin
+	cmd.Dir = modRoot
+	return cmd.Run()
+}


Test patch:
diff --git a/cl/compile_test.go b/cl/compile_test.go
index cb560c52..ebf1386f 100644
--- a/cl/compile_test.go
+++ b/cl/compile_test.go
@@ -23,13 +23,14 @@ import (
 	"sync"
 	"testing"
 
+	"github.com/goplus/gop"
 	"github.com/goplus/gop/cl"
 	"github.com/goplus/gop/parser"
 	"github.com/goplus/gop/parser/parsertest"
 	"github.com/goplus/gop/scanner"
 	"github.com/goplus/gop/token"
 	"github.com/goplus/gox"
-	"github.com/goplus/gox/packages"
+	"github.com/goplus/mod/env"
 )
 
 const (
@@ -45,7 +46,7 @@ func init() {
 	gox.SetDebug(gox.DbgFlagAll)
 	cl.SetDebug(cl.DbgFlagAll)
 	gblFset = token.NewFileSet()
-	imp := packages.NewImporter(gblFset)
+	imp := gop.NewImporter(nil, &env.Gop{Root: gopRootDir, Version: "1.0"}, gblFset)
 	gblConf = &cl.Config{
 		Fset:          gblFset,
 		Importer:      imp,
@@ -3421,7 +3422,7 @@ func removeAutogenFiles() {
 	os.Remove("./internal/gop-in-go/foo/gop_autogen2_test.go")
 }
 
-func _TestImportGopPkg(t *testing.T) {
+func TestImportGopPkg(t *testing.T) {
 	autogen.Lock()
 	defer autogen.Unlock()
 
@@ -3445,15 +3446,6 @@ func main() {
 }
 
 func TestCallDep(t *testing.T) {
-	const (
-		cachedir  = "../.gop"
-		cachefile = cachedir + "/gop.cache"
-	)
-	os.Remove(cachefile)
-	defer func() {
-		os.Remove(cachefile)
-		os.Remove(cachedir)
-	}()
 	for i := 0; i < 2; i++ {
 		gopClTest(t, `
 import (