Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gop.mod: allow to define multiple projects #39

Merged
merged 2 commits into from
Jan 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions gopmod/classfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}

Expand Down
78 changes: 37 additions & 41 deletions modfile/gop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down Expand Up @@ -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)
}
}

Expand Down Expand Up @@ -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
Expand All @@ -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`, `
Expand Down
37 changes: 23 additions & 14 deletions modfile/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -199,22 +207,23 @@ 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)
if err != nil {
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 {
Expand All @@ -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,
Expand Down
10 changes: 7 additions & 3 deletions modload/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,12 +193,16 @@ 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 (p Module) HasProject() bool {
return len(p.Opt.Projects) > 0
}

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.
Expand Down