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: new import statement #51

Merged
merged 1 commit 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
15 changes: 15 additions & 0 deletions modfile/gop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,21 @@ class ."spx Sprite
doTestParseErr(t, `gop.mod:3: symbol sprite invalid: invalid Go export symbol format`, `
project github.com/goplus/spx math
class .spx sprite
`)
doTestParseErr(t, `gop.mod:3: usage: import [name] pkgPath`, `
project github.com/goplus/spx math
import
`)
doTestParseErr(t, `gop.mod:3: invalid quoted string: invalid syntax`, `
project github.com/goplus/spx math
import "\?"
`)
doTestParseErr(t, `gop.mod:3: invalid syntax`, `
project github.com/goplus/spx math
import "\?" math
`)
doTestParseErr(t, `gop.mod:2: import must declare after a project definition`, `
import math
`)
doTestParseErr(t, `gop.mod:2: unknown directive: unknown`, `
unknown .spx
Expand Down
32 changes: 6 additions & 26 deletions modfile/regtest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@
package modfile_test

import (
"os"
"testing"

"github.com/goplus/mod/gopmod"
"github.com/goplus/mod/modload"
"github.com/goplus/mod/modload/modtest"
)

func TestGopMod(t *testing.T) {
Expand All @@ -43,29 +42,10 @@ func TestGopMod(t *testing.T) {
}
}

func TestLoadFromEx(t *testing.T) {
const gomodText = `
module github.com/goplus/community

go 1.18
func TestGopClass(t *testing.T) {
modtest.GopClass(t)
}

require (
github.com/goplus/yap v0.5.0 //gop:class
github.com/qiniu/a v0.1.0
github.com/qiniu/x v1.13.2 // gop:class
)
`
const gomod = "go.mod"
mod, err := modload.LoadFromEx(gomod, "gop.mod", func(s string) ([]byte, error) {
if s == gomod {
return []byte(gomodText), nil
}
return nil, os.ErrNotExist
})
if err != nil {
t.Fatal("LoadFromEx:", err)
}
if n := len(mod.Opt.ClassMods); n != 2 {
t.Fatal("len(mod.Opt.Import):", n)
}
func TestImport(t *testing.T) {
modtest.Import(t)
}
85 changes: 57 additions & 28 deletions modfile/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (
type File struct {
Gop *Gop
Projects []*Project
ClassMods []string
ClassMods []string // calc by require statements in go.mod (not gop.mod).

Syntax *FileSyntax
}
Expand All @@ -51,18 +51,27 @@ func (p *File) proj() *Project { // current project
// A Gop is the gop statement.
type Gop = modfile.Go

// A Register is the //gop:class statement.
type Register struct {
ClassfileMod string // module path of classfile
Syntax *Line
// A Class is the work class statement.
type Class struct {
Ext string // can be "_[class].gox" or ".[class]", eg "_yap.gox" or ".spx"
Class string // "Sprite"
Syntax *Line
}

// A Import is the import statement.
type Import struct {
Name string // maybe empty
Path string
Syntax *Line
}

// A Project is the project statement.
type Project struct {
Ext string // can be "_[class].gox" or ".[class]", eg "_yap.gox" or ".gmx"
Class string // "Game"
Works []*Class // work class of classfile
PkgPaths []string // package paths of classfile
Ext string // can be "_[class].gox" or ".[class]", eg "_yap.gox" or ".gmx"
Class string // "Game"
Works []*Class // work class of classfile
PkgPaths []string // package paths of classfile and optional inline-imported packages.
Import []*Import // auto-imported packages
Syntax *Line
}

Expand All @@ -79,13 +88,6 @@ func (p *Project) IsProj(ext, fname string) bool {
return true
}

// A Class is the work class statement.
type Class struct {
Ext string // can be "_[class].gox" or ".[class]", eg "_yap.gox" or ".spx"
Class string // "Sprite"
Syntax *Line
}

func New(gopmod, gopVer string) *File {
gop := &Line{
Token: []string{"gop", gopVer},
Expand Down Expand Up @@ -251,6 +253,34 @@ func (f *File) parseVerb(errs *ErrorList, verb string, line *Line, args []string
Class: class,
Syntax: line,
})
case "import":
proj := f.proj()
if proj == nil {
errorf("import must declare after a project definition")
return
}
var name string
switch len(args) {
case 2:
v, err := parseString(&args[0])
if err != nil {
wrapError(err)
return
}
name = v
args = args[1:]
fallthrough
case 1:
pkgPath, err := parsePkgPath(&args[0])
if err != nil {
wrapError(err)
return
}
proj.Import = append(proj.Import, &Import{Name: name, Path: pkgPath, Syntax: line})
default:
errorf("usage: import [name] pkgPath")
return
}
default:
if strict {
errorf("unknown directive: %s", verb)
Expand Down Expand Up @@ -320,23 +350,22 @@ func parseString(s *string) (string, error) {
return t, nil
}

func parseStrings(args []string) (arr []string, err error) {
arr = make([]string, len(args))
for i := range args {
if arr[i], err = parseString(&args[i]); err != nil {
return
}
func parsePkgPath(s *string) (path string, err error) {
if path, err = parseString(s); err != nil {
err = fmt.Errorf("invalid quoted string: %v", err)
return
}
if !isPkgPath(path) {
err = fmt.Errorf(`"%s" is not a valid package path`, path)
}
return
}

func parsePkgPaths(args []string) (paths []string, err error) {
if paths, err = parseStrings(args); err != nil {
return nil, fmt.Errorf("invalid quoted string: %v", err)
}
for _, pkg := range paths {
if !isPkgPath(pkg) {
return nil, fmt.Errorf(`"%s" is not a valid package path`, pkg)
paths = make([]string, len(args))
for i := range args {
if paths[i], err = parsePkgPath(&args[i]); err != nil {
return
}
}
return
Expand Down
85 changes: 85 additions & 0 deletions modload/modtest/modtest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2024 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 modtest

import (
"os"
"testing"

"github.com/goplus/mod/modload"
)

func LoadFrom(gomod, gopmod string, gomodText, gopmodText string) (mod modload.Module, err error) {
return modload.LoadFromEx(gomod, gopmod, func(s string) ([]byte, error) {
if s == gomod {
return []byte(gomodText), nil
} else if s == gopmod && gopmodText != "" {
return []byte(gopmodText), nil
}
return nil, os.ErrNotExist
})
}

func Load(t *testing.T, gomodText, gopmodText string, errMsg string) modload.Module {
mod, err := LoadFrom("/foo/go.mod", "/foo/gop.mod", gomodText, gopmodText)
if err != nil {
if err.Error() != errMsg {
t.Fatal("LoadFrom:", err)
}
}
return mod
}

func GopClass(t *testing.T) {
const gomodText = `
module github.com/goplus/community

go 1.18

require (
github.com/goplus/yap v0.5.0 //gop:class
github.com/qiniu/a v0.1.0
github.com/qiniu/x v1.13.2 // gop:class
)
`
mod := Load(t, gomodText, ``, ``)
if n := len(mod.Opt.ClassMods); n != 2 {
t.Fatal("len(mod.Opt.Import):", n)
}
}

func Import(t *testing.T) {
const gomodText = `
module github.com/goplus/yap

go 1.18
`
const gopmodText = `
gop 1.2

project _yap.gox App github.com/goplus/yap

project _ytest.gox App github.com/goplus/yap/test
class _ytest.gox Case
import github.com/goplus/yap/ytest/auth/jwt
import yauth github.com/goplus/yap/ytest/auth
`
mod := Load(t, gomodText, gopmodText, ``)
if n := len(mod.Opt.Projects); n != 2 {
t.Fatal("len(mod.Opt.Projects):", n)
}
}
31 changes: 31 additions & 0 deletions modload/regtest_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2024 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 modload_test

import (
"testing"

"github.com/goplus/mod/modload/modtest"
)

func TestGopClass(t *testing.T) {
modtest.GopClass(t)
}

func TestImport(t *testing.T) {
modtest.Import(t)
}
Loading