diff --git a/cl/builtin_test.go b/cl/builtin_test.go index 88cd15e7c..f5211fa71 100644 --- a/cl/builtin_test.go +++ b/cl/builtin_test.go @@ -550,13 +550,18 @@ func lookupClassErr(ext string) (c *modfile.Project, ok bool) { } func TestGetGoFile(t *testing.T) { - if f := genGoFile("a_test.gop", false); f != testingGoFile { + ctx := &pkgCtx{} + if f := ctx.genGoFile("a_test.gop", false); f != testingGoFile { t.Fatal("TestGetGoFile:", f) } - if f := genGoFile("a_test.gox", true); f != testingGoFile { + if f := ctx.genGoFile("a_test.gox", true); f != testingGoFile { t.Fatal("TestGetGoFile:", f) } - if f := genGoFile("a.gop", false); f != defaultGoFile { + if f := ctx.genGoFile("a.gop", false); f != defaultGoFile { + t.Fatal("TestGetGoFile:", f) + } + ctx.multiFiles = true + if f := ctx.genGoFile("a.gop", false); f != "a.gop" { t.Fatal("TestGetGoFile:", f) } } diff --git a/cl/classfile.go b/cl/classfile.go index 0356b363b..91d253b52 100644 --- a/cl/classfile.go +++ b/cl/classfile.go @@ -55,6 +55,7 @@ type gmxProject struct { gameIsPtr bool isTest bool hasMain_ bool + file string } func (p *gmxProject) hasMain() bool { @@ -319,14 +320,14 @@ func gmxProjMain(pkg *gogen.Package, parent *pkgCtx, proj *gmxProject) { classType = base.Name() proj.gameClass = classType } - + goFile := parent.genGoFile(proj.file, false) ld := getTypeLoader(parent, parent.syms, token.NoPos, proj.gameClass) if ld.typ == nil { ld.typ = func() { if debugLoad { log.Println("==> Load > NewType", classType) } - old, _ := pkg.SetCurFile(defaultGoFile, true) + old, _ := pkg.SetCurFile(goFile, true) defer pkg.RestoreCurFile(old) baseType := base.Type() @@ -342,7 +343,7 @@ func gmxProjMain(pkg *gogen.Package, parent *pkgCtx, proj *gmxProject) { if debugLoad { log.Println("==> Load > InitType", classType) } - old, _ := pkg.SetCurFile(defaultGoFile, true) + old, _ := pkg.SetCurFile(goFile, true) defer pkg.RestoreCurFile(old) decl.InitType(pkg, types.NewStruct(flds, nil)) @@ -351,7 +352,7 @@ func gmxProjMain(pkg *gogen.Package, parent *pkgCtx, proj *gmxProject) { } } ld.methods = append(ld.methods, func() { - old, _ := pkg.SetCurFile(defaultGoFile, true) + old, _ := pkg.SetCurFile(goFile, true) defer pkg.RestoreCurFile(old) doInitType(ld) @@ -360,7 +361,7 @@ func gmxProjMain(pkg *gogen.Package, parent *pkgCtx, proj *gmxProject) { fn := pkg.NewFunc(recv, "Main", nil, nil, false) parent.inits = append(parent.inits, func() { - old, _ := pkg.SetCurFile(defaultGoFile, true) + old, _ := pkg.SetCurFile(goFile, true) defer pkg.RestoreCurFile(old) cb := fn.BodyStart(pkg).Typ(base.Type()).MemberVal("Main") @@ -389,9 +390,11 @@ func gmxProjMain(pkg *gogen.Package, parent *pkgCtx, proj *gmxProject) { }) } -func gmxMainFunc(pkg *gogen.Package, proj *gmxProject) func() { +func gmxMainFunc(pkg *gogen.Package, ctx *pkgCtx, proj *gmxProject) func() { return func() { if o := pkg.TryRef(proj.gameClass); o != nil { + old, _ := pkg.SetCurFile(ctx.genGoFile(proj.file, false), true) + defer pkg.RestoreCurFile(old) // new(gameClass).Main() new := pkg.Builtin().Ref("new") pkg.NewFunc(nil, "main", nil, nil, false). diff --git a/cl/compile.go b/cl/compile.go index 377988999..e1ac31410 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -203,6 +203,9 @@ type Config struct { // Outline = true means to skip compiling function bodies. Outline bool + + // MultiFiles = true means generate multi files. + MultiFiles bool } type nodeInterp struct { @@ -342,6 +345,8 @@ type pkgCtx struct { generics map[string]bool // generic type record idents []*ast.Ident // toType ident recored inInst int // toType in generic instance + + multiFiles bool // generate multi files } type pkgImp struct { @@ -501,6 +506,7 @@ func NewPackage(pkgPath string, pkg *ast.Package, conf *Config) (p *gogen.Packag overpos: make(map[string]token.Pos), syms: make(map[string]loader), generics: make(map[string]bool), + multiFiles: conf.MultiFiles, } confGox := &gogen.Config{ Types: conf.Types, @@ -609,7 +615,7 @@ func NewPackage(pkgPath string, pkg *ast.Package, conf *Config) (p *gogen.Packag if genMain { // make classfile main func if need if proj != nil && !multi { // only one project file - gen = gmxMainFunc(p, proj) + gen = gmxMainFunc(p, ctx, proj) } } @@ -634,7 +640,7 @@ func NewPackage(pkgPath string, pkg *ast.Package, conf *Config) (p *gogen.Packag if gen != nil { // generate classfile main func gen() } else if genMain && !conf.NoAutoGenMain { // generate empty main func - old, _ := p.SetCurFile(defaultGoFile, false) + old, _ := p.SetCurFile(ctx.genGoFile("", false), false) p.NewFunc(nil, "main", nil, nil, false).BodyStart(p).End() p.RestoreCurFile(old) } @@ -702,10 +708,13 @@ func loadFile(ctx *pkgCtx, f *ast.File) { // // *_test.gop // *test.gox -func genGoFile(file string, goxTestFile bool) string { +func (ctx *pkgCtx) genGoFile(file string, goxTestFile bool) string { if goxTestFile || strings.HasSuffix(file, "_test.gop") { return testingGoFile } + if ctx.multiFiles { + return file + } return defaultGoFile } @@ -744,6 +753,7 @@ func preloadGopFile(p *gogen.Package, ctx *blockCtx, file string, f *ast.File, c if proj.gameIsPtr { baseType = types.NewPointer(baseType) } + proj.file = file } else { o := proj.sprite[c.ext] ctx.baseClass = o @@ -751,7 +761,7 @@ func preloadGopFile(p *gogen.Package, ctx *blockCtx, file string, f *ast.File, c } } } - goFile := genGoFile(file, goxTestFile) + goFile := ctx.genGoFile(file, goxTestFile) if classType != "" { if debugLoad { log.Println("==> Preload type", classType) diff --git a/cmd/internal/clean/clean.go b/cmd/internal/clean/clean.go index a06c5fcee..eeea08ce0 100644 --- a/cmd/internal/clean/clean.go +++ b/cmd/internal/clean/clean.go @@ -27,6 +27,7 @@ import ( ) const ( + autoGenFilePrefix = "gop_autogen_" autoGenFileSuffix = "_autogen.go" autoGenTestFile = "gop_autogen_test.go" autoGen2TestFile = "gop_autogen2_test.go" @@ -53,7 +54,7 @@ func cleanAGFiles(dir string, execAct bool) { } continue } - if strings.HasSuffix(fname, autoGenFileSuffix) { + if strings.HasSuffix(fname, autoGenFileSuffix) || strings.HasPrefix(fname, autoGenFilePrefix) { file := filepath.Join(dir, fname) fmt.Printf("Cleaning %s ...\n", file) if execAct { diff --git a/cmd/internal/gengo/go.go b/cmd/internal/gengo/go.go index d66682b92..68f5d849e 100644 --- a/cmd/internal/gengo/go.go +++ b/cmd/internal/gengo/go.go @@ -44,6 +44,7 @@ var ( flagSingleMode = flag.Bool("s", false, "run in single file mode for package") flagIgnoreNotatedErr = flag.Bool( "ignore-notated-error", false, "ignore notated errors, only available together with -t (check mode)") + flagMultiFiles = flag.Bool("multi-files", false, "genarate multi files for package") ) func init() { @@ -87,6 +88,9 @@ func runCmd(cmd *base.Command, args []string) { if *flagSingleMode { flags |= gop.GenFlagSingleFile } + if *flagMultiFiles { + flags |= gop.GenFlagMultiFiles + } for _, proj := range projs { switch v := proj.(type) { case *gopprojs.DirProj: diff --git a/gengo.go b/gengo.go index 336bf21ec..1d48b1072 100644 --- a/gengo.go +++ b/gengo.go @@ -24,6 +24,7 @@ import ( "strings" "syscall" + "github.com/goplus/gogen" "github.com/goplus/mod/gopmod" "github.com/goplus/mod/modcache" "github.com/goplus/mod/modfetch" @@ -35,6 +36,7 @@ const ( autoGenFile = "gop_autogen.go" autoGenTestFile = "gop_autogen_test.go" autoGen2TestFile = "gop_autogen2_test.go" + autoGenPrefix = "gop_autogen_" ) type GenFlags int @@ -42,6 +44,7 @@ type GenFlags int const ( GenFlagCheckOnly GenFlags = 1 << iota GenFlagSingleFile + GenFlagMultiFiles GenFlagPrintError GenFlagPrompt ) @@ -166,7 +169,7 @@ func genGoSingleFile(file string, conf *Config, flags GenFlags) (err error) { } func genGoIn(dir string, conf *Config, genTestPkg bool, flags GenFlags, gen ...*bool) (err error) { - out, test, err := LoadDir(dir, conf, genTestPkg, (flags&GenFlagPrompt) != 0) + out, test, err := LoadDir(dir, conf, genTestPkg, (flags&GenFlagPrompt) != 0, (flags&GenFlagMultiFiles) != 0) if err != nil { if NotFound(err) { // no Go+ source files return nil @@ -177,10 +180,18 @@ func genGoIn(dir string, conf *Config, genTestPkg bool, flags GenFlags, gen ...* return nil } os.MkdirAll(dir, 0755) - file := filepath.Join(dir, autoGenFile) - err = out.WriteFile(file) - if err != nil { - return errors.NewWith(err, `out.WriteFile(file)`, -2, "(*gogen.Package).WriteFile", out, file) + + if flags&GenFlagMultiFiles != 0 { + err = writeMultiFiles(out, dir) + if err != nil { + return errors.NewWith(err, `writeMultiFiles(out, dir)`, -2, "(*gogen.Package).WriteFile", out, dir) + } + } else { + file := filepath.Join(dir, autoGenFile) + err = out.WriteFile(file) + if err != nil { + return errors.NewWith(err, `out.WriteFile(file)`, -2, "(*gogen.Package).WriteFile", out, file) + } } if gen != nil { // say `gop_autogen.go generated` *gen[0] = true @@ -204,6 +215,29 @@ func genGoIn(dir string, conf *Config, genTestPkg bool, flags GenFlags, gen ...* return } +func writeMultiFiles(pkg *gogen.Package, dir string) error { + names := make(map[string]string) + pkg.ForEachFile(func(fname string, file *gogen.File) { + if fname == "" { + names[fname] = autoGenFile + } else { + _, name := filepath.Split(fname) + name = name[:len(name)-len(filepath.Ext(name))] + if strings.HasSuffix(name, "_test") { + return + } + names[fname] = autoGenPrefix + name + ".go" + } + }) + for fname, file := range names { + err := pkg.WriteFile(filepath.Join(dir, file), fname) + if err != nil { + return err + } + } + return nil +} + // ----------------------------------------------------------------------------- const ( diff --git a/load.go b/load.go index f6c3cf468..84ac026a8 100644 --- a/load.go +++ b/load.go @@ -272,6 +272,9 @@ func LoadDir(dir string, conf *Config, genTestPkg bool, promptGenGo ...bool) (ou Importer: imp, LookupClass: mod.LookupClass, } + if len(promptGenGo) > 1 && promptGenGo[1] { + clConf.MultiFiles = true + } for name, pkg := range pkgs { if strings.HasSuffix(name, "_test") {