Skip to content

Commit

Permalink
feat(cmd/web/schema): 添加 Schema
Browse files Browse the repository at this point in the history
  • Loading branch information
caixw committed Dec 6, 2023
1 parent 3c56c0d commit bf6b43d
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 89 deletions.
4 changes: 2 additions & 2 deletions cmd/web/restdoc/parser/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,11 @@ func (p *Parser) addQuery(t *openapi.OpenAPI, opt *openapi3.Operation, currPath,
return
}

s, err := schema.New(p.pkgs, t, currPath, suffix, true)
s, err := p.schema.New(t, currPath, suffix, true)
if err != nil {
var serr *schema.Error
if errors.As(err, &serr) {
serr.Log(p.l, p.pkgs.Fset)
serr.Log(p.l, p.schema.Packages().FileSet())
return
}
p.l.Error(err, filename, ln)
Expand Down
8 changes: 4 additions & 4 deletions cmd/web/restdoc/parser/body.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ func (p *Parser) parseRequest(o *openapi3.Operation, t *openapi.OpenAPI, suffix,
return
}

s, err := schema.New(p.pkgs, t, currPath, words[1], false)
s, err := p.schema.New(t, currPath, words[1], false)
if err != nil {
var serr *schema.Error
if errors.As(err, &serr) {
serr.Log(p.l, p.pkgs.Fset)
serr.Log(p.l, p.schema.Packages().FileSet())
return
}
p.l.Error(err, filename, ln)
Expand All @@ -51,11 +51,11 @@ func (p *Parser) parseResponse(resps map[string]*openapi3.Response, t *openapi.O
return false
}

s, err := schema.New(p.pkgs, t, currPath, words[2], false)
s, err := p.schema.New(t, currPath, words[2], false)
if err != nil {
var serr *schema.Error
if errors.As(err, &serr) {
serr.Log(p.l, p.pkgs.Fset)
serr.Log(p.l, p.schema.Packages().FileSet())
return false
}
p.l.Error(err, filename, ln)
Expand Down
15 changes: 9 additions & 6 deletions cmd/web/restdoc/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ import (
"github.com/issue9/web/cmd/web/restdoc/logger"
"github.com/issue9/web/cmd/web/restdoc/openapi"
"github.com/issue9/web/cmd/web/restdoc/pkg"
"github.com/issue9/web/cmd/web/restdoc/schema"
"github.com/issue9/web/cmd/web/restdoc/utils"
)

// Parser 文档分析对象
type Parser struct {
pkgs *pkg.Packages
schema *schema.Schema

media []string // 全局可用 media type
resps map[string]*openapi3.Response // 全局可用 response
Expand Down Expand Up @@ -60,7 +61,7 @@ type comments struct {
// tags 如果非空,则表示仅返回带这些标签的 API;
func New(l *logger.Logger, prefix string, tags []string) *Parser {
return &Parser{
pkgs: pkg.New(l),
schema: schema.New(l),

apiComments: make([]*comments, 0, 100),

Expand All @@ -79,13 +80,15 @@ func (p *Parser) AddDir(ctx context.Context, root string, recursive bool) {
if p.parsed {
panic("已经解析完成,无法再次添加!")
}
p.pkgs.ScanDir(ctx, root, recursive)
p.schema.Packages().ScanDir(ctx, root, recursive)
}

// line 返回 pos 的行号
func (p *Parser) line(pos token.Pos) int { return p.pkgs.Position(pos).Line }
func (p *Parser) line(pos token.Pos) int { return p.schema.Packages().FileSet().Position(pos).Line }

func (p *Parser) file(pos token.Pos) string { return p.pkgs.Position(pos).Filename }
func (p *Parser) file(pos token.Pos) string {
return p.schema.Packages().FileSet().Position(pos).Filename
}

// Parse 解析由 [Parser.AddDir] 加载的内容
func (p *Parser) Parse(ctx context.Context) *openapi.OpenAPI {
Expand All @@ -94,7 +97,7 @@ func (p *Parser) Parse(ctx context.Context) *openapi.OpenAPI {
t := openapi.New("3.0.0")
wg := &sync.WaitGroup{}

p.pkgs.Range(func(pp *packages.Package) bool {
p.schema.Packages().Range(func(pp *packages.Package) bool {
select {
case <-ctx.Done():
p.l.Warning(pkg.Cancelled)
Expand Down
2 changes: 1 addition & 1 deletion cmd/web/restdoc/parser/restdoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ func (p *Parser) parseConstVersion(path, pkgPath string) (string, error) {
path = path[index+1:]
}

pkg := p.pkgs.Package(pkgPath)
pkg := p.schema.Packages().Package(pkgPath)
for _, f := range pkg.Syntax {
for _, d := range f.Decls {
g, ok := d.(*ast.GenDecl)
Expand Down
18 changes: 13 additions & 5 deletions cmd/web/restdoc/pkg/pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package pkg
import (
"context"
"go/token"
"go/types"
"path/filepath"
"slices"
"sync"
Expand All @@ -25,14 +26,14 @@ const Cancelled = web.StringPhrase("cancelled")
type Packages struct {
pkgsM sync.Mutex
pkgs []*packages.Package
Fset *token.FileSet
fset *token.FileSet
l *logger.Logger
}

func New(l *logger.Logger) *Packages {
return &Packages{
pkgs: make([]*packages.Package, 0, 10),
Fset: token.NewFileSet(),
fset: token.NewFileSet(),
l: l,
}
}
Expand Down Expand Up @@ -65,7 +66,7 @@ func (pkgs *Packages) ScanDir(ctx context.Context, root string, recursive bool)
Mode: mode,
Context: ctx,
Dir: dir,
Fset: pkgs.Fset,
Fset: pkgs.fset,
})
if err != nil {
pkgs.l.Error(err, "", 0)
Expand All @@ -89,13 +90,20 @@ func (pkgs *Packages) append(ps ...*packages.Package) {
}
}

func (pkgs *Packages) FileSet() *token.FileSet { return pkgs.fset }

func (pkgs *Packages) Package(path string) *packages.Package {
pkg, _ := sliceutil.At(pkgs.pkgs, func(p *packages.Package, _ int) bool { return p.PkgPath == path })
return pkg
}

func (pkgs *Packages) Position(p token.Pos) token.Position {
return pkgs.Fset.Position(p)
func (pkgs *Packages) Lookup(name string) types.Object {
for _, p := range pkgs.pkgs {
if obj := p.Types.Scope().Lookup(name); obj != nil {
return obj
}
}
return nil
}

// f 如果返回了 false,将退出循环
Expand Down
17 changes: 8 additions & 9 deletions cmd/web/restdoc/schema/generics.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,24 @@ import (
"strings"

"github.com/issue9/web/cmd/web/restdoc/openapi"
"github.com/issue9/web/cmd/web/restdoc/pkg"
)

type typeParam struct {
ref *Ref
name string // 类型参数的实参名称
}

func fromIndexExprType(pkg *pkg.Packages, t *openapi.OpenAPI, file *ast.File, currPath, tag string, idx *ast.IndexExpr) (*Ref, error) {
func (s *Schema) fromIndexExprType(t *openapi.OpenAPI, file *ast.File, currPath, tag string, idx *ast.IndexExpr) (*Ref, error) {
mod, idxName := getExprName(file, currPath, idx.Index)
if mod != currPath {
idxName = mod + "." + idxName
}

mod, name := getExprName(file, currPath, idx.X)
return fromName(pkg, t, mod, name+"["+idxName+"]", tag, false)
return s.fromName(t, mod, name+"["+idxName+"]", tag, false)
}

func fromIndexListExprType(pkg *pkg.Packages, t *openapi.OpenAPI, file *ast.File, currPath, tag string, idx *ast.IndexListExpr) (*Ref, error) {
func (s *Schema) fromIndexListExprType(t *openapi.OpenAPI, file *ast.File, currPath, tag string, idx *ast.IndexListExpr) (*Ref, error) {
indexes := make([]string, 0, len(idx.Indices))
for _, i := range idx.Indices {
mod, idxName := getExprName(file, currPath, i)
Expand All @@ -38,10 +37,10 @@ func fromIndexListExprType(pkg *pkg.Packages, t *openapi.OpenAPI, file *ast.File

mod, name := getExprName(file, currPath, idx.X)
name += "[" + strings.Join(indexes, ",") + "]"
return fromName(pkg, t, mod, name, tag, false)
return s.fromName(t, mod, name, tag, false)
}

func fromIndexExpr(pkg *pkg.Packages, t *openapi.OpenAPI, file *ast.File, currPath, tag string, idx *ast.IndexExpr, refs map[string]*typeParam) (*Ref, error) {
func (s *Schema) fromIndexExpr(t *openapi.OpenAPI, file *ast.File, currPath, tag string, idx *ast.IndexExpr, refs map[string]*typeParam) (*Ref, error) {
mod, idxName := getExprName(file, currPath, idx.Index)
if mod != currPath {
idxName = mod + "." + idxName
Expand All @@ -52,10 +51,10 @@ func fromIndexExpr(pkg *pkg.Packages, t *openapi.OpenAPI, file *ast.File, currPa
}

mod, name := getExprName(file, currPath, idx.X)
return fromName(pkg, t, mod, name+"["+idxName+"]", tag, false)
return s.fromName(t, mod, name+"["+idxName+"]", tag, false)
}

func fromIndexListExpr(pkg *pkg.Packages, t *openapi.OpenAPI, file *ast.File, currPath, tag string, idx *ast.IndexListExpr, refs map[string]*typeParam) (*Ref, error) {
func (s *Schema) fromIndexListExpr(t *openapi.OpenAPI, file *ast.File, currPath, tag string, idx *ast.IndexListExpr, refs map[string]*typeParam) (*Ref, error) {
indexes := make([]string, 0, len(idx.Indices))
for _, i := range idx.Indices {
mod, idxName := getExprName(file, currPath, i)
Expand All @@ -71,7 +70,7 @@ func fromIndexListExpr(pkg *pkg.Packages, t *openapi.OpenAPI, file *ast.File, cu

mod, name := getExprName(file, currPath, idx.X)
name += "[" + strings.Join(indexes, ",") + "]"
return fromName(pkg, t, mod, name, tag, false)
return s.fromName(t, mod, name, tag, false)
}

func getExprName(file *ast.File, currPath string, expr ast.Expr) (mod, name string) {
Expand Down
12 changes: 12 additions & 0 deletions cmd/web/restdoc/schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (

"github.com/getkin/kin-openapi/openapi3"

"github.com/issue9/web/cmd/web/restdoc/logger"
"github.com/issue9/web/cmd/web/restdoc/pkg"
"github.com/issue9/web/cmd/web/restdoc/utils"
)

Expand All @@ -25,6 +27,16 @@ var refReplacer = strings.NewReplacer(

type Ref = openapi3.SchemaRef

// Schema 管理 Schema 的查询
type Schema struct {
pkg *pkg.Packages
}

func New(l *logger.Logger) *Schema { return &Schema{pkg: pkg.New(l)} }

// Packages 返回关联的 [pkg.Packages]
func (s *Schema) Packages() *pkg.Packages { return s.pkg }

func addRefPrefix(ref string) string {
if !strings.HasPrefix(ref, refPrefix) {
ref = refPrefix + ref
Expand Down
Loading

0 comments on commit bf6b43d

Please sign in to comment.