goctl support import api file (#94)

* rebase upstream

* rebase

* trim no need line

* trim no need line

* trim no need line

* update doc

* remove update

* remove no need

* remove no need

* goctl add jwt support

* goctl add jwt support

* goctl add jwt support

* goctl support import

* goctl support import

Co-authored-by: kingxt <dream4kingxt@163.com>
master
kingxt 4 years ago committed by GitHub
parent be9c48da7f
commit b628bc0086
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -65,16 +65,16 @@ func ApiFormat(path string, printToConsole bool) error {
return m return m
}) })
info, st, service, err := parser.MatchStruct(r) apiStruct, err := parser.MatchStruct(r)
if err != nil { if err != nil {
return err return err
} }
info = strings.TrimSpace(info) info := strings.TrimSpace(apiStruct.Info)
if len(service) == 0 || len(st) == 0 { if len(apiStruct.Service) == 0 {
return nil return nil
} }
fs, err := format.Source([]byte(strings.TrimSpace(st))) fs, err := format.Source([]byte(strings.TrimSpace(apiStruct.StructBody)))
if err != nil { if err != nil {
str := err.Error() str := err.Error()
lineNumber := strings.Index(str, ":") lineNumber := strings.Index(str, ":")
@ -93,12 +93,24 @@ func ApiFormat(path string, printToConsole bool) error {
return err return err
} }
result := strings.Join([]string{info, string(fs), service}, "\n\n") var result string
if len(strings.TrimSpace(info)) > 0 {
result += strings.TrimSpace(info) + "\n\n"
}
if len(strings.TrimSpace(apiStruct.Imports)) > 0 {
result += strings.TrimSpace(apiStruct.Imports) + "\n\n"
}
if len(strings.TrimSpace(string(fs))) > 0 {
result += strings.TrimSpace(string(fs)) + "\n\n"
}
if len(strings.TrimSpace(apiStruct.Service)) > 0 {
result += strings.TrimSpace(apiStruct.Service) + "\n\n"
}
if printToConsole { if printToConsole {
_, err := fmt.Print(result) _, err := fmt.Print(result)
return err return err
} }
result = strings.TrimSpace(result)
return ioutil.WriteFile(path, []byte(result), os.ModePerm) return ioutil.WriteFile(path, []byte(result), os.ModePerm)
} }

@ -6,36 +6,61 @@ import (
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"path/filepath"
"strings"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/tal-tech/go-zero/tools/goctl/api/spec"
"github.com/tal-tech/go-zero/tools/goctl/util"
) )
type Parser struct { type Parser struct {
r *bufio.Reader r *bufio.Reader
st string typeDef string
} }
func NewParser(filename string) (*Parser, error) { func NewParser(filename string) (*Parser, error) {
apiAbsPath, err := filepath.Abs(filename)
if err != nil {
return nil, err
}
api, err := ioutil.ReadFile(filename) api, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }
info, body, service, err := MatchStruct(string(api))
apiStruct, err := MatchStruct(string(api))
if err != nil {
return nil, err
}
for _, item := range strings.Split(apiStruct.Imports, "\n") {
ip := strings.TrimSpace(item)
if len(ip) > 0 {
item := strings.TrimPrefix(item, "import")
item = strings.TrimSpace(item)
var path = item
if !util.FileExists(item) {
path = filepath.Join(filepath.Dir(apiAbsPath), item)
}
content, err := ioutil.ReadFile(path)
if err != nil { if err != nil {
return nil, err return nil, err
} }
apiStruct.StructBody += "\n" + string(content)
}
}
var buffer = new(bytes.Buffer) var buffer = new(bytes.Buffer)
buffer.WriteString(info) buffer.WriteString(apiStruct.Service)
buffer.WriteString(service)
return &Parser{ return &Parser{
r: bufio.NewReader(buffer), r: bufio.NewReader(buffer),
st: body, typeDef: apiStruct.StructBody,
}, nil }, nil
} }
func (p *Parser) Parse() (api *spec.ApiSpec, err error) { func (p *Parser) Parse() (api *spec.ApiSpec, err error) {
api = new(spec.ApiSpec) api = new(spec.ApiSpec)
types, err := parseStructAst(p.st) types, err := parseStructAst(p.typeDef)
if err != nil { if err != nil {
return nil, err return nil, err
} }

@ -3,19 +3,19 @@ package parser
import ( import (
"bufio" "bufio"
"errors" "errors"
"regexp"
"strings" "strings"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/tal-tech/go-zero/tools/goctl/api/spec"
) )
// struct match var emptyType spec.Type
const typeRegex = `(?m)(?m)(^ *type\s+[a-zA-Z][a-zA-Z0-9_-]+\s+(((struct)\s*?\{[\w\W]*?[^\{]\})|([a-zA-Z][a-zA-Z0-9_-]+)))|(^ *type\s*?\([\w\W]+\}\s*\))`
var ( type ApiStruct struct {
emptyStrcut = errors.New("struct body not found") Info string
emptyType spec.Type StructBody string
) Service string
Imports string
}
func GetType(api *spec.ApiSpec, t string) spec.Type { func GetType(api *spec.ApiSpec, t string) spec.Type {
for _, tp := range api.Types { for _, tp := range api.Types {
@ -69,32 +69,56 @@ func unread(r *bufio.Reader) error {
return r.UnreadRune() return r.UnreadRune()
} }
func MatchStruct(api string) (info, structBody, service string, err error) { func MatchStruct(api string) (*ApiStruct, error) {
r := regexp.MustCompile(typeRegex) var result ApiStruct
indexes := r.FindAllStringIndex(api, -1) scanner := bufio.NewScanner(strings.NewReader(api))
if len(indexes) == 0 { var parseInfo = false
return "", "", "", emptyStrcut var parseImport = false
var parseType = false
var parseSevice = false
var segment string
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "@doc(" {
parseInfo = true
}
if line == ")" && parseInfo {
parseInfo = false
result.Info = segment + ")"
segment = ""
continue
} }
startIndexes := indexes[0]
endIndexes := indexes[len(indexes)-1]
info = api[:startIndexes[0]]
structBody = api[startIndexes[0]:endIndexes[len(endIndexes)-1]]
service = api[endIndexes[len(endIndexes)-1]:]
firstIIndex := strings.Index(info, "i") if strings.HasPrefix(line, "import") {
if firstIIndex > 0 { parseImport = true
info = info[firstIIndex:] }
if parseImport && (strings.HasPrefix(line, "type") || strings.HasPrefix(line, "@server") ||
strings.HasPrefix(line, "service")) {
parseImport = false
result.Imports = segment
segment = line + "\n"
continue
} }
lastServiceRightBraceIndex := strings.LastIndex(service, "}") + 1 if strings.HasPrefix(line, "type") {
var firstServiceIndex int parseType = true
for index, char := range service {
if !isSpace(char) && !isNewline(char) {
firstServiceIndex = index
break
} }
if strings.HasPrefix(line, "@server") || strings.HasPrefix(line, "service") {
if parseType {
parseType = false
result.StructBody = segment
segment = line + "\n"
continue
}
parseSevice = true
}
segment += scanner.Text() + "\n"
}
if !parseSevice {
return nil, errors.New("no service defined")
} }
service = service[firstServiceIndex:lastServiceRightBraceIndex] result.Service = segment
return return &result, nil
} }

Loading…
Cancel
Save