From 4fef59113b3d77d47b6b249e03d6961d6799fdd9 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Sun, 7 Jan 2024 17:53:02 +0800 Subject: [PATCH 1/2] gop.mod: allow define multiple projects --- gopmod/classfile.go | 10 +++--- modfile/gop_test.go | 78 +++++++++++++++++++++------------------------ modfile/rule.go | 37 +++++++++++++-------- modload/module.go | 6 ++-- 4 files changed, 69 insertions(+), 62 deletions(-) diff --git a/gopmod/classfile.go b/gopmod/classfile.go index da090dc..49a6260 100644 --- a/gopmod/classfile.go +++ b/gopmod/classfile.go @@ -80,7 +80,7 @@ func (p *Module) ImportClasses(importClass ...func(c *Project)) (err error) { p.importClass(SpxProject, impcls) p.projects[".gmx"] = SpxProject // old style opt := p.Opt - if c := opt.Project; c != nil { + for _, c := range opt.Projects { p.importClass(c, impcls) } for _, r := range opt.Import { @@ -116,11 +116,13 @@ func (p *Module) importClassFrom(modVer module.Version, impcls func(c *Project)) if err != nil { return } - c := mod.Project() - if c == nil { + projs := mod.Projects() + if len(projs) == 0 { return ErrNotClassFileMod } - p.importClass(c, impcls) + for _, c := range projs { + p.importClass(c, impcls) + } return } diff --git a/modfile/gop_test.go b/modfile/gop_test.go index 7ae9253..974faf6 100644 --- a/modfile/gop_test.go +++ b/modfile/gop_test.go @@ -94,38 +94,38 @@ func TestParse1(t *testing.T) { if f.Gop.Version != "1.1" { t.Errorf("gop version expected be 1.1, but %s got", f.Gop.Version) } - if f.Project.Ext != ".gmx" { - t.Errorf("project exts expected be .gmx, but %s got", f.Project.Ext) + if f.proj().Ext != ".gmx" { + t.Errorf("project exts expected be .gmx, but %s got", f.proj().Ext) } - if f.Project.Class != "Game" { - t.Errorf("project class expected be Game, but %s got", f.Project.Class) + if f.proj().Class != "Game" { + t.Errorf("project class expected be Game, but %s got", f.proj().Class) } - if len(f.Project.PkgPaths) != 2 { - t.Errorf("project pkgpaths length expected be 2, but %d got", len(f.Project.PkgPaths)) + if len(f.proj().PkgPaths) != 2 { + t.Errorf("project pkgpaths length expected be 2, but %d got", len(f.proj().PkgPaths)) } - if f.Project.PkgPaths[0] != "github.com/goplus/spx" { - t.Errorf("project path expected be github.com/goplus/spx, but %s got", f.Project.PkgPaths[0]) + if f.proj().PkgPaths[0] != "github.com/goplus/spx" { + t.Errorf("project path expected be github.com/goplus/spx, but %s got", f.proj().PkgPaths[0]) } - if f.Project.PkgPaths[1] != "math" { - t.Errorf("project path expected be math, but %s got", f.Project.PkgPaths[1]) + if f.proj().PkgPaths[1] != "math" { + t.Errorf("project path expected be math, but %s got", f.proj().PkgPaths[1]) } - if len(f.Project.Works) != 2 { - t.Errorf("project workclass length expected be 2, but %d got", len(f.Project.Works)) + if len(f.proj().Works) != 2 { + t.Errorf("project workclass length expected be 2, but %d got", len(f.proj().Works)) } - if f.Project.Works[0].Ext != ".spx" { - t.Errorf("project class[0] exts expected be .spx, but %s got", f.Project.Works[0].Ext) + if f.proj().Works[0].Ext != ".spx" { + t.Errorf("project class[0] exts expected be .spx, but %s got", f.proj().Works[0].Ext) } - if f.Project.Works[0].Class != "Sprite" { - t.Errorf("project class[0] class expected be Sprite, but %s got", f.Project.Works[0].Class) + if f.proj().Works[0].Class != "Sprite" { + t.Errorf("project class[0] class expected be Sprite, but %s got", f.proj().Works[0].Class) } - if f.Project.Works[1].Ext != ".spx2" { - t.Errorf("project class[1] exts expected be .spx2, but %s got", f.Project.Works[1].Ext) + if f.proj().Works[1].Ext != ".spx2" { + t.Errorf("project class[1] exts expected be .spx2, but %s got", f.proj().Works[1].Ext) } - if f.Project.Works[1].Class != "*Sprite2" { - t.Errorf("project class[1] class expected be Sprite, but %s got", f.Project.Works[1].Class) + if f.proj().Works[1].Class != "*Sprite2" { + t.Errorf("project class[1] class expected be Sprite, but %s got", f.proj().Works[1].Class) } } @@ -197,32 +197,32 @@ func TestParse2(t *testing.T) { if f.Gop.Version != "1.1" { t.Errorf("gop version expected be 1.1, but %s got", f.Gop.Version) } - if f.Project.Ext != "" { - t.Errorf("project exts expected be .gmx, but %s got", f.Project.Ext) + if f.proj().Ext != "" { + t.Errorf("project exts expected be .gmx, but %s got", f.proj().Ext) } - if f.Project.Class != "" { - t.Errorf("project class expected be Game, but %s got", f.Project.Class) + if f.proj().Class != "" { + t.Errorf("project class expected be Game, but %s got", f.proj().Class) } - if len(f.Project.PkgPaths) != 2 { - t.Errorf("project pkgpaths length expected be 2, but %d got", len(f.Project.PkgPaths)) + if len(f.proj().PkgPaths) != 2 { + t.Errorf("project pkgpaths length expected be 2, but %d got", len(f.proj().PkgPaths)) } - if f.Project.PkgPaths[0] != "github.com/goplus/spx" { - t.Errorf("project path expected be github.com/goplus/spx, but %s got", f.Project.PkgPaths[0]) + if f.proj().PkgPaths[0] != "github.com/goplus/spx" { + t.Errorf("project path expected be github.com/goplus/spx, but %s got", f.proj().PkgPaths[0]) } - if f.Project.PkgPaths[1] != "math" { - t.Errorf("project path expected be math, but %s got", f.Project.PkgPaths[1]) + if f.proj().PkgPaths[1] != "math" { + t.Errorf("project path expected be math, but %s got", f.proj().PkgPaths[1]) } - if len(f.Project.Works) != 1 { - t.Errorf("project workclass length expected be 2, but %d got", len(f.Project.Works)) + if len(f.proj().Works) != 1 { + t.Errorf("project workclass length expected be 2, but %d got", len(f.proj().Works)) } - if f.Project.Works[0].Ext != ".spx" { - t.Errorf("project class[0] exts expected be .spx, but %s got", f.Project.Works[0].Ext) + if f.proj().Works[0].Ext != ".spx" { + t.Errorf("project class[0] exts expected be .spx, but %s got", f.proj().Works[0].Ext) } - if f.Project.Works[0].Class != "Sprite" { - t.Errorf("project class[0] class expected be Sprite, but %s got", f.Project.Works[0].Class) + if f.proj().Works[0].Class != "Sprite" { + t.Errorf("project class[0] class expected be Sprite, but %s got", f.proj().Works[0].Class) } } @@ -279,10 +279,6 @@ register "\?" `) doTestParseErr(t, `gop.mod:2: malformed module path "-": leading dash`, ` register - -`) - doTestParseErr(t, `gop.mod:3: repeated project statement`, ` -project .gmx Game github.com/goplus/spx math -project .gmx Game github.com/goplus/spx math `) doTestParseErr(t, `gop.mod:2: usage: project [.projExt ProjClass] classFilePkgPath ...`, ` project @@ -305,7 +301,7 @@ project .123 Game "\?" doTestParseErr(t, `gop.mod:2: invalid quoted string: invalid syntax`, ` project "\?" `) - doTestParseErr(t, `gop.mod:2: work class must declare a project`, ` + doTestParseErr(t, `gop.mod:2: work class must declare after a project definition`, ` class .spx Sprite `) doTestParseErr(t, `gop.mod:3: usage: class .workExt WorkClass`, ` diff --git a/modfile/rule.go b/modfile/rule.go index 0178585..b58207c 100644 --- a/modfile/rule.go +++ b/modfile/rule.go @@ -30,13 +30,25 @@ import ( // A File is the parsed, interpreted form of a gop.mod file. type File struct { - Gop *Gop - Project *Project - Import []*Import + Gop *Gop + Projects []*Project + Import []*Import Syntax *FileSyntax } +func (p *File) addProj(proj *Project) { + p.Projects = append(p.Projects, proj) +} + +func (p *File) proj() *Project { // current project + n := len(p.Projects) + if n == 0 { + return nil + } + return p.Projects[n-1] +} + // A Module is the module statement. type Module = modfile.Module @@ -171,10 +183,6 @@ func (f *File) parseVerb(errs *ErrorList, verb string, line *Line, args []string Syntax: line, }) case "project": - if f.Project != nil { - errorf("repeated project statement") - return - } if len(args) < 1 { errorf("usage: project [.projExt ProjClass] classFilePkgPath ...") return @@ -199,9 +207,9 @@ func (f *File) parseVerb(errs *ErrorList, verb string, line *Line, args []string errorf("invalid quoted string: %v", err) return } - f.Project = &Project{ + f.addProj(&Project{ Ext: ext, Class: class, PkgPaths: pkgPaths, Syntax: line, - } + }) return } pkgPaths, err := parseStrings(args) @@ -209,12 +217,13 @@ func (f *File) parseVerb(errs *ErrorList, verb string, line *Line, args []string errorf("invalid quoted string: %v", err) return } - f.Project = &Project{ + f.addProj(&Project{ PkgPaths: pkgPaths, Syntax: line, - } + }) case "class": - if f.Project == nil { - errorf("work class must declare a project") + proj := f.proj() + if proj == nil { + errorf("work class must declare after a project definition") return } if len(args) < 2 { @@ -231,7 +240,7 @@ func (f *File) parseVerb(errs *ErrorList, verb string, line *Line, args []string wrapError(err) return } - f.Project.Works = append(f.Project.Works, &Class{ + proj.Works = append(proj.Works, &Class{ Ext: workExt, Class: class, Syntax: line, diff --git a/modload/module.go b/modload/module.go index 765d2ca..ea06926 100644 --- a/modload/module.go +++ b/modload/module.go @@ -193,12 +193,12 @@ func LoadFrom(gomod, gopmod string) (p Module, err error) { // ----------------------------------------------------------------------------- -func (p Module) Project() *modfile.Project { - return p.Opt.Project +func (p Module) Projects() []*modfile.Project { + return p.Opt.Projects } func hasGopExtended(opt *modfile.File) bool { - return opt.Project != nil || len(opt.Import) > 0 + return len(opt.Projects) > 0 || len(opt.Import) > 0 } // Save saves all changes of this module. From 303af2af4c3f535e495e36ae35315dda3152c72f Mon Sep 17 00:00:00 2001 From: xushiwei Date: Sun, 7 Jan 2024 18:00:31 +0800 Subject: [PATCH 2/2] Module: HasProject --- modload/module.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modload/module.go b/modload/module.go index ea06926..24dc4ef 100644 --- a/modload/module.go +++ b/modload/module.go @@ -197,6 +197,10 @@ func (p Module) Projects() []*modfile.Project { return p.Opt.Projects } +func (p Module) HasProject() bool { + return len(p.Opt.Projects) > 0 +} + func hasGopExtended(opt *modfile.File) bool { return len(opt.Projects) > 0 || len(opt.Import) > 0 }