Skip to content

Commit

Permalink
refactor(cmd/web/restdoc): 在类型未找到时会加载所有模块的依赖代码
Browse files Browse the repository at this point in the history
  • Loading branch information
caixw committed May 10, 2024
1 parent 7eab358 commit 4431b00
Show file tree
Hide file tree
Showing 14 changed files with 65 additions and 139 deletions.
18 changes: 9 additions & 9 deletions cmd/web/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@ module github.com/issue9/web/cmd/web
go 1.22.0

require (
github.com/caixw/gobuild v1.7.5
github.com/caixw/gobuild v1.7.6
github.com/getkin/kin-openapi v0.124.0
github.com/issue9/assert/v4 v4.3.0
github.com/issue9/cmdopt v0.13.1
github.com/issue9/localeutil v0.26.7
github.com/issue9/logs/v7 v7.6.0
github.com/issue9/mux/v8 v8.1.0
github.com/issue9/localeutil v0.26.9
github.com/issue9/logs/v7 v7.6.1
github.com/issue9/mux/v8 v8.1.1
github.com/issue9/query/v3 v3.1.3
github.com/issue9/sliceutil v0.16.1
github.com/issue9/source v0.9.1
github.com/issue9/term/v3 v3.2.8
github.com/issue9/source v0.11.1
github.com/issue9/term/v3 v3.2.9
github.com/issue9/version v1.0.8
github.com/issue9/web v0.93.2
github.com/issue9/web v0.94.1
golang.org/x/mod v0.17.0
golang.org/x/text v0.15.0
golang.org/x/tools v0.20.0
golang.org/x/tools v0.21.0
gopkg.in/yaml.v3 v3.0.1
)

Expand All @@ -42,6 +42,6 @@ require (
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
)
32 changes: 16 additions & 16 deletions cmd/web/go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/caixw/gobuild v1.7.5 h1:zvhWgqfiAsxGSDKTOUU8sgjG9+bYA5BGEVCo4nMYg2Q=
github.com/caixw/gobuild v1.7.5/go.mod h1:xPlFk/6N+71b+sp43b7X8uua7pP7lQMWWoKKhwczosI=
github.com/caixw/gobuild v1.7.6 h1:NnLQQWuKeA5lNt6gmABxg0DIlx1t9WkdiFMEj40PknQ=
github.com/caixw/gobuild v1.7.6/go.mod h1:F8XPRaVhtjqP3MrXLOAokFWGcyW+n15rPAv5IBWNBa8=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
Expand All @@ -28,12 +28,12 @@ github.com/issue9/conv v1.3.5 h1:UWeA+Zqp5vjNDLrmhLhaXPjS1hL8gh4quX6Shk5njKQ=
github.com/issue9/conv v1.3.5/go.mod h1:lkZYMyrmxy+HK//N4eLmwUl9mCwj0zgeTjnxgl/w7hM=
github.com/issue9/errwrap v0.3.2 h1:7KEme9Pfe75M+sIMcPCn/DV90wjnOcRbO4DXVAHj3Fw=
github.com/issue9/errwrap v0.3.2/go.mod h1:KcCLuUGiffjooLCUjL89r1cyO8/HT/VRcQrneO53N3A=
github.com/issue9/localeutil v0.26.7 h1:LLpzBoZhAmRUqyDuveWNq+LA7hxD2G2ZJvjhRYrhikg=
github.com/issue9/localeutil v0.26.7/go.mod h1:TNoqmrux5wJwS2ZcZw4qwMPJx8nmxta5OchfAKQbYaI=
github.com/issue9/logs/v7 v7.6.0 h1:dvY1ctPROdd2YaOwYRNOkfbmMx+8OM0w53t8bWrWg9s=
github.com/issue9/logs/v7 v7.6.0/go.mod h1:7Hx1vnAojUciyFdqNlMiwsBJRGBc/P2Yrjt7ACm9Uno=
github.com/issue9/mux/v8 v8.1.0 h1:NZmQv0iE0ocn1oyHWKZWY+PIVcbpZYdaDImJ3+WJ/28=
github.com/issue9/mux/v8 v8.1.0/go.mod h1:ivUHUcMzoTPxvjC33XrsWJ68fnw5vEjJ0y1GcuMrg84=
github.com/issue9/localeutil v0.26.9 h1:T8qZICA9LshXrW6W3txReps4XalgTUn273M4oSXirkE=
github.com/issue9/localeutil v0.26.9/go.mod h1:TNoqmrux5wJwS2ZcZw4qwMPJx8nmxta5OchfAKQbYaI=
github.com/issue9/logs/v7 v7.6.1 h1:eUuzmj0USsFR8mMHrtcJcMym175F6Boen3pmAD7rBhE=
github.com/issue9/logs/v7 v7.6.1/go.mod h1:qB5EKf6G+CkVQbHhWmaClhP8OkWzdAhCWvk9FJ1CJqA=
github.com/issue9/mux/v8 v8.1.1 h1:LhDrYz1+1KTaylIniinRFhiXvnLKhdvcp/fibXiJWeA=
github.com/issue9/mux/v8 v8.1.1/go.mod h1:lutTRmqmf2XUsD05nVSdPZ4JO1qPZ1KsUYVjKzj/F9w=
github.com/issue9/query/v3 v3.1.3 h1:Y6ETEYXxaKqhpM4lXPKCffhJ72VuKQbrAwgwHlacu0Y=
github.com/issue9/query/v3 v3.1.3/go.mod h1:a/W/+7iel9K+5rRT4AFAKR8+OJeV5axeF6tK9My4lNA=
github.com/issue9/rands/v3 v3.0.1 h1:EnX9WNushGgHCzoL/R5eBPaLfvjLO/c7CGHNgLK0JhY=
Expand All @@ -42,10 +42,10 @@ github.com/issue9/scheduled v0.20.0 h1:tFehe5MhCUNS/E9VC8et0uO7N1Z09PmOAPWZD0cMW
github.com/issue9/scheduled v0.20.0/go.mod h1:zx5rYymWhJpHWXa9CchbzXa0VqBMUPNGV3n9fBUhe9c=
github.com/issue9/sliceutil v0.16.1 h1:NVZ2feN014oUmMpZvZUrKkKMGhAfzT8WNzJF81krebM=
github.com/issue9/sliceutil v0.16.1/go.mod h1:ldun6sT4/bOJxuMtOXhtc6P7GCwE7L+avV86HNks7qk=
github.com/issue9/source v0.9.1 h1:duANl/q03NzDtZN5sOPia+s4vBu8c1CqtHGoluY0Tto=
github.com/issue9/source v0.9.1/go.mod h1:8L8ef8XhMftlE2ZQ8j60h5hTGlQmPjm/8zvoXr5fnTY=
github.com/issue9/term/v3 v3.2.8 h1:vAtsr9FLwrDQRyU7S8AOUI3f+QrYsXVHT/kee9MuMkk=
github.com/issue9/term/v3 v3.2.8/go.mod h1:S/xLgjEXJNr7C6UhcGTEOV5k94mzHRcYMmtvhLJoX6A=
github.com/issue9/source v0.11.1 h1:nLb8k8TtMr9CZOx6NWiAAgVJ3caJotkrLVZSv9RYV48=
github.com/issue9/source v0.11.1/go.mod h1:MQYr1hupicwivCqFSH4FAc+eMT6VMTmKTNJOvqRacG0=
github.com/issue9/term/v3 v3.2.9 h1:0hRJjErY0PWzSkoOCwZ1bBxUw8w9ctblNFBZn8Na1kM=
github.com/issue9/term/v3 v3.2.9/go.mod h1:NkoNf6ANL+bIgT2CZFi6aD1Q2yeksxAr2mb+Nhb9+r4=
github.com/issue9/unique/v2 v2.1.0 h1:lE9hstenrbBgDM/Iulv7d75qAYpgoDV8rSRoLmEBHOk=
github.com/issue9/unique/v2 v2.1.0/go.mod h1:qZoDKnfu+7Q0yxhifVseRKD2Wea9Tc9zdXwALnFc54A=
github.com/issue9/version v1.0.8 h1:IsNdDYdV8UGDGwwgp8H4RszJE0Ko26HjWg9pZzyOivs=
Expand Down Expand Up @@ -80,12 +80,12 @@ golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY=
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
1 change: 1 addition & 0 deletions cmd/web/locale/locale.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ func Init(opt *cmdopt.CmdOpt, p *localeutil.Printer) {
Recursive: *r,
SkipSubModule: *skip,
WarnLog: log.ERROR().LocaleString,
InfoLog: func(localeutil.Stringer) {}, // 默认不输出提示信息
Funcs: strings.Split(*funcs, ","),
}
if *i {
Expand Down
8 changes: 2 additions & 6 deletions cmd/web/locales/locales.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,10 @@ import (
//go:embed *.yaml
var locales embed.FS

var Locales = []fs.FS{
var Locales = append([]fs.FS{
locales,
gobuild.Locales,
}

func init() {
Locales = append(Locales, web.Locales...)
}
}, web.Locales...)

func NewPrinter(lang string) (*localeutil.Printer, error) {
tag, err := language.Parse(lang)
Expand Down
6 changes: 0 additions & 6 deletions cmd/web/locales/und.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,6 @@ messages:
- key: override global response %s
message:
msg: override global response %s
- key: parse module dependencies
message:
msg: parse module dependencies
- key: parse replace direct, only valid when d is true
message:
msg: parse replace direct, only valid when d is true
- key: recursive dir
message:
msg: recursive dir
Expand Down
6 changes: 0 additions & 6 deletions cmd/web/locales/zh-CN.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,6 @@ messages:
- key: override global response %s
message:
msg: '%s 与定义的全局对象相同,在当前接口中将覆盖全局定义。'
- key: parse module dependencies
message:
msg: 同时也对模块的直接依赖进行解析
- key: parse replace direct, only valid when d is true
message:
msg: 是否解析 go.mod 中的 replace 指令,仅在 -d 参数为 true 时有效。
- key: recursive dir
message:
msg: 递归访问子目录
Expand Down
17 changes: 11 additions & 6 deletions cmd/web/restdoc/pkg/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import (
"context"
"fmt"
"go/ast"
"go/build"
"go/token"
"go/types"
"path"
"slices"
"strconv"
"strings"

"github.com/issue9/source"
"golang.org/x/tools/go/packages"
)

Expand Down Expand Up @@ -208,14 +208,15 @@ func filterVersionSuffix(p string, separator byte) (string, bool) {

// 如果是内置类型,那么返回参数中的 TypeSpec 为 nil;
// 返回的 bool 表示是否找到了 path 对应的类型;
// typePath 的路径部分应该是真实的路径而不是 Import 中的别名;
func (pkgs *Packages) lookup(ctx context.Context, typePath string) (types.Object, *ast.TypeSpec, *ast.File, bool) {
if typePath == "" {
panic("参数 path 不能为空")
}

var pkgPath string
typeName := typePath
// 防止出现 github.com/pkg/pkg.type/name 等不规则内容,type/name 并不是一个合法法的类型名
// 防止出现 github.com/pkg/pkg.type/name 等不规则内容,type/name 并不是一个合法的类型名
if index := strings.LastIndexByte(typePath, '.'); index > 0 && !strings.ContainsRune(typePath[index:], '/') {
pkgPath = typePath[:index]
typeName = typePath[index+1:]
Expand All @@ -225,10 +226,14 @@ func (pkgs *Packages) lookup(ctx context.Context, typePath string) (types.Object
return o, ts, f, true
}

// 出于性能考虑并未加载依赖项,但是可能会依赖部分标准库的类型,
// 此处对标准库作了特殊处理:未找到标准库中的对象时会加载相应的包。
if pkgPath != "" && strings.IndexByte(pkgPath, '.') < 0 {
dir := path.Join(build.Default.GOROOT, "src", pkgPath)
// 碰到未找到的类型,尝试加载依赖包。

for pkgDir := range pkgs.pkgs {
dir, err := source.PkgSourceDir(pkgPath, pkgDir, true)
if err != nil {
return nil, nil, nil, false
}

p, err := pkgs.load(ctx, dir)
if err != nil {
pkgs.l.Error(err, "", 0)
Expand Down
1 change: 1 addition & 0 deletions cmd/web/restdoc/pkg/pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func (pkgs *Packages) ScanDir(ctx context.Context, root string, recursive bool)
wg.Wait()
}

// 加载 dir 目录下的包,如果已经加载,则直接从缓存中读取。
func (pkgs *Packages) load(ctx context.Context, dir string) (*packages.Package, error) {
dir = filepath.Clean(dir)

Expand Down
46 changes: 1 addition & 45 deletions cmd/web/restdoc/restdoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,13 @@ package restdoc
import (
"context"
"flag"
"go/build"
"io"
"os"
"path/filepath"
"slices"
"strings"

"github.com/issue9/cmdopt"
"github.com/issue9/localeutil"
"github.com/issue9/source"
"github.com/issue9/web"
"golang.org/x/mod/modfile"

"github.com/issue9/web/cmd/web/restdoc/logger"
"github.com/issue9/web/cmd/web/restdoc/parser"
Expand All @@ -32,9 +27,7 @@ const (
outputUsage = web.StringPhrase("set output file")
recursiveUsage = web.StringPhrase("recursive dir")
tagUsage = web.StringPhrase("filter by tag")
depUsage = web.StringPhrase("parse module dependencies")
prefixUsage = web.StringPhrase("set api path prefix")
replaceUsage = web.StringPhrase("parse replace direct, only valid when d is true")
)

const defaultOutput = "./restdoc.json"
Expand All @@ -44,9 +37,7 @@ func Init(opt *cmdopt.CmdOpt, p *localeutil.Printer) {
output := fs.String("o", defaultOutput, outputUsage.LocaleString(p))
recursive := fs.Bool("r", true, recursiveUsage.LocaleString(p))
t := fs.String("t", "", tagUsage.LocaleString(p))
dep := fs.Bool("d", false, depUsage.LocaleString(p))
urlPrefix := fs.String("p", "", prefixUsage.LocaleString(p))
replace := fs.Bool("replace", true, replaceUsage.LocaleString(p))

return func(io.Writer) error {
ctx := context.Background()
Expand All @@ -62,29 +53,10 @@ func Init(opt *cmdopt.CmdOpt, p *localeutil.Printer) {
if *t != "" {
tags = strings.Split(*t, ",")
}
dp := parser.New(l, *urlPrefix, tags)

dp := parser.New(l, *urlPrefix, tags)
for _, dir := range fs.Args() {
dp.AddDir(ctx, dir, *recursive)

if *dep {
path, mod, err := source.ModFile(dir)
if err != nil {
return err
}

for _, p := range mod.Require {
if p.Indirect {
continue
}

modDir, err := getRealPath(*replace, mod, p, filepath.Dir(path))
if err != nil {
return err
}
dp.AddDir(ctx, modDir, *recursive)
}
}
}

if doc := dp.Parse(ctx); doc != nil {
Expand All @@ -97,19 +69,3 @@ func Init(opt *cmdopt.CmdOpt, p *localeutil.Printer) {
}
})
}

var modCache = filepath.Join(build.Default.GOPATH, "pkg", "mod")

func getRealPath(replace bool, mod *modfile.File, pkg *modfile.Require, dir string) (string, error) {
if replace && len(mod.Replace) > 0 {
index := slices.IndexFunc(mod.Replace, func(r *modfile.Replace) bool { return r.Old.Path == pkg.Mod.Path })
if index >= 0 {
p := mod.Replace[index].New.Path
if !filepath.IsAbs(p) {
p = filepath.Join(dir, p)
}
return filepath.Abs(p)
}
}
return filepath.Join(modCache, pkg.Mod.Path+"@"+pkg.Mod.Version), nil
}
21 changes: 0 additions & 21 deletions cmd/web/restdoc/restdoc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,10 @@ package restdoc
import (
"flag"
"os"
"path/filepath"
"strings"
"testing"

"github.com/issue9/assert/v4"
"github.com/issue9/cmdopt"
"github.com/issue9/source"
"github.com/issue9/web"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"

"github.com/issue9/web/cmd/web/locales"
)
Expand All @@ -33,18 +27,3 @@ func TestInit(t *testing.T) {
err = opt.Exec([]string{"restdoc", "-o=" + path, "./parser/testdata"})
a.NotError(err).FileExists(path)
}

func TestGetRealPath(t *testing.T) {
a := assert.New(t, false)

path, mod, err := source.ModFile(".")
a.NotError(err).NotNil(mod)
dir := filepath.Dir(path)

p1, err := getRealPath(false, mod, &modfile.Require{Mod: module.Version{Path: "github.com/issue9/web", Version: web.Version}}, dir)
a.NotError(err).
True(strings.HasSuffix(p1, "web@"+web.Version))

p2, err := getRealPath(true, mod, &modfile.Require{Mod: module.Version{Path: "github.com/issue9/web", Version: web.Version}}, dir)
a.NotError(err).NotEqual(p1, p2)
}
14 changes: 7 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ require (
github.com/issue9/config v0.6.2
github.com/issue9/conv v1.3.5
github.com/issue9/errwrap v0.3.2
github.com/issue9/localeutil v0.26.7
github.com/issue9/logs/v7 v7.6.0
github.com/issue9/mux/v8 v8.1.0
github.com/issue9/localeutil v0.26.9
github.com/issue9/logs/v7 v7.6.1
github.com/issue9/mux/v8 v8.1.1
github.com/issue9/query/v3 v3.1.3
github.com/issue9/scheduled v0.20.0
github.com/issue9/sliceutil v0.16.1
github.com/issue9/source v0.9.1
github.com/issue9/term/v3 v3.2.8
github.com/issue9/source v0.11.1
github.com/issue9/term/v3 v3.2.9
github.com/issue9/unique/v2 v2.1.0
github.com/jellydator/ttlcache/v3 v3.2.0
github.com/klauspost/compress v1.17.8
golang.org/x/crypto v0.22.0
golang.org/x/crypto v0.23.0
golang.org/x/text v0.15.0
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028
gopkg.in/yaml.v3 v3.0.1
Expand All @@ -37,5 +37,5 @@ require (
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/sys v0.20.0 // indirect
)
Loading

0 comments on commit 4431b00

Please sign in to comment.