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

modfile: Import => ClassMods #49

Merged
merged 2 commits into from
Jan 31, 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
4 changes: 2 additions & 2 deletions gopmod/classfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ func (p *Module) ImportClasses(importClass ...func(c *Project)) (err error) {
for _, c := range opt.Projects {
p.importClass(c, impcls)
}
for _, r := range opt.Import {
if err = p.importMod(r.ClassfileMod, impcls); err != nil {
for _, classMod := range opt.ClassMods {
if err = p.importMod(classMod, impcls); err != nil {
return
}
}
Expand Down
54 changes: 0 additions & 54 deletions modfile/gop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,23 +62,6 @@ func lookupClass(ext string) (c *Project, ok bool) {
return
}

func TestUpdateLine(t *testing.T) {
line := &Line{InBlock: true}
updateLine(line, "foo", "bar")
if len(line.Token) != 1 && line.Token[0] != "bar" {
t.Fatal("updateLine failed:", line.Token)
}
}

func TestGetWeight(t *testing.T) {
if getWeight(&modfile.LineBlock{Token: []string{"gop"}}) != directiveGop {
t.Fatal("getWeight require failed")
}
if getWeight(&modfile.LineBlock{Token: []string{"unknown"}}) != directiveLineBlock {
t.Fatal("getWeight unknown failed")
}
}

// -----------------------------------------------------------------------------

const gopmodSpx1 = `
Expand Down Expand Up @@ -265,34 +248,6 @@ func TestParse2(t *testing.T) {
}
}

const gopmodUserProj = `
gop 1.1

import github.com/goplus/spx
`

func TestParseUser(t *testing.T) {
const (
gopmod = gopmodUserProj
)
f, err := Parse("github.com/goplus/gop/gop.mod", []byte(gopmod), nil)
if err != nil || len(f.Import) != 1 {
t.Fatal("Parse:", f, err)
return
}
if f.Import[0].ClassfileMod != "github.com/goplus/spx" {
t.Fatal("Parse => Register:", f.Import)
}
f.AddImport("github.com/goplus/spx")
if len(f.Import) != 1 {
t.Fatal("AddRegister not exist?")
}
f.AddImport("github.com/xushiwei/foogop")
if len(f.Import) != 2 {
t.Fatal("AddRegister failed")
}
}

func TestParseErr(t *testing.T) {
doTestParseErr(t, `gop.mod:2: unknown directive: module`, `
module foo
Expand All @@ -309,15 +264,6 @@ gop 1.1 1.2
`)
doTestParseErr(t, `gop.mod:2: invalid gop version '1.x': must match format 1.23`, `
gop 1.x
`)
doTestParseErr(t, `gop.mod:2: import directive expects exactly one argument`, `
register 1 2 3
`)
doTestParseErr(t, `gop.mod:2: invalid quoted string: invalid syntax`, `
register "\?"
`)
doTestParseErr(t, `gop.mod:2: malformed module path "-": leading dash`, `
register -
`)
doTestParseErr(t, `gop.mod:2: usage: project [.projExt ProjClass] classFilePkgPath ...`, `
project
Expand Down
8 changes: 0 additions & 8 deletions modfile/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ type Line = modfile.Line
// "x"
// "y"
// )
//
type LineBlock = modfile.LineBlock

// An LParen represents the beginning of a parenthesized line block.
Expand All @@ -59,10 +58,3 @@ type LParen = modfile.LParen
// An RParen represents the end of a parenthesized line block.
// It is a place to store whole-line (before) comments.
type RParen = modfile.RParen

// ModulePath returns the module path from the gopmod file text.
// If it cannot find a module path, it returns an empty string.
// It is tolerant of unrelated problems in the gop.mod file.
func ModulePath(mod []byte) string {
return modfile.ModulePath(mod)
}
64 changes: 0 additions & 64 deletions modfile/read_test.go

This file was deleted.

2 changes: 1 addition & 1 deletion modfile/regtest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ require (
if err != nil {
t.Fatal("LoadFromEx:", err)
}
if n := len(mod.Opt.Import); n != 2 {
if n := len(mod.Opt.ClassMods); n != 2 {
t.Fatal("len(mod.Opt.Import):", n)
}
}
147 changes: 21 additions & 126 deletions modfile/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,13 @@ import (

"github.com/qiniu/x/errors"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
)

// A File is the parsed, interpreted form of a gop.mod file.
type File struct {
Gop *Gop
Projects []*Project
Import []*Import
Gop *Gop
Projects []*Project
ClassMods []string

Syntax *FileSyntax
}
Expand All @@ -49,14 +48,11 @@ func (p *File) proj() *Project { // current project
return p.Projects[n-1]
}

// A Module is the module statement.
type Module = modfile.Module

// A Gop is the gop statement.
type Gop = modfile.Go

// A Import is the import statement.
type Import struct {
// A Register is the //gop:class statement.
type Register struct {
ClassfileMod string // module path of classfile
Syntax *Line
}
Expand Down Expand Up @@ -90,6 +86,22 @@ type Class struct {
Syntax *Line
}

func New(gopmod, gopVer string) *File {
gop := &Line{
Token: []string{"gop", gopVer},
}
return &File{
Gop: &Gop{
Version: gopVer,
Syntax: gop,
},
Syntax: &FileSyntax{
Name: gopmod,
Stmt: []Expr{gop},
},
}
}

type VersionFixer = modfile.VersionFixer

// Parse parses and returns a gop.mod file.
Expand Down Expand Up @@ -176,25 +188,6 @@ func (f *File) parseVerb(errs *ErrorList, verb string, line *Line, args []string
}
f.Gop = &Gop{Syntax: line}
f.Gop.Version = args[0]
case "import", "register": // register => import
if len(args) != 1 {
errorf("import directive expects exactly one argument")
return
}
s, err := parseString(&args[0])
if err != nil {
errorf("invalid quoted string: %v", err)
return
}
err = module.CheckPath(s)
if err != nil {
wrapError(err)
return
}
f.Import = append(f.Import, &Import{
ClassfileMod: s,
Syntax: line,
})
case "project":
if len(args) < 1 {
errorf("usage: project [.projExt ProjClass] classFilePkgPath ...")
Expand Down Expand Up @@ -382,101 +375,3 @@ func (p *Error) Summary() string {
}

// -----------------------------------------------------------------------------

const (
directiveInvalid = iota
directiveModule
directiveGop
directiveProject
directiveClass
)

const (
directiveLineBlock = 0x80 + iota
directiveImport
)

var directiveWeights = map[string]int{
"module": directiveModule,
"gop": directiveGop,
"import": directiveImport,
"register": directiveImport, // register => import
"project": directiveProject,
"class": directiveClass,
}

func getWeight(e Expr) int {
if line, ok := e.(*Line); ok {
return directiveWeights[line.Token[0]]
}
if w, ok := directiveWeights[e.(*LineBlock).Token[0]]; ok {
return w
}
return directiveLineBlock
}

func updateLine(line *Line, tokens ...string) {
if line.InBlock {
tokens = tokens[1:]
}
line.Token = tokens
}

func addLine(x *FileSyntax, tokens ...string) *Line {
new := &Line{Token: tokens}
w := directiveWeights[tokens[0]]
for i, e := range x.Stmt {
w2 := getWeight(e)
if w <= w2 {
x.Stmt = append(x.Stmt, nil)
copy(x.Stmt[i+1:], x.Stmt[i:])
x.Stmt[i] = new
return new
}
}
x.Stmt = append(x.Stmt, new)
return new
}

func (f *File) AddGopStmt(version string) error {
if !modfile.GoVersionRE.MatchString(version) {
return fmt.Errorf("invalid language version string %q", version)
}
if f.Gop == nil {
if f.Syntax == nil {
f.Syntax = new(FileSyntax)
}
f.Gop = &Gop{
Version: version,
Syntax: addLine(f.Syntax, "gop", version),
}
} else {
f.Gop.Version = version
updateLine(f.Gop.Syntax, "gop", version)
}
return nil
}

func (f *File) AddImport(modPath string) {
for _, r := range f.Import {
if r.ClassfileMod == modPath {
return
}
}
f.AddNewImport(modPath)
}

func (f *File) AddNewImport(modPath string) {
line := addLine(f.Syntax, "import", AutoQuote(modPath))
r := &Import{
ClassfileMod: modPath,
Syntax: line,
}
f.Import = append(f.Import, r)
}

func (f *File) Format() ([]byte, error) {
return modfile.Format(f.Syntax), nil
}

// -----------------------------------------------------------------------------
Loading
Loading