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>
This commit is contained in:
@@ -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 {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
||||||
|
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
|
||||||
startIndexes := indexes[0]
|
var parseSevice = false
|
||||||
endIndexes := indexes[len(indexes)-1]
|
var segment string
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := strings.TrimSpace(scanner.Text())
|
||||||
|
|
||||||
info = api[:startIndexes[0]]
|
if line == "@doc(" {
|
||||||
structBody = api[startIndexes[0]:endIndexes[len(endIndexes)-1]]
|
parseInfo = true
|
||||||
service = api[endIndexes[len(endIndexes)-1]:]
|
|
||||||
|
|
||||||
firstIIndex := strings.Index(info, "i")
|
|
||||||
if firstIIndex > 0 {
|
|
||||||
info = info[firstIIndex:]
|
|
||||||
}
|
|
||||||
|
|
||||||
lastServiceRightBraceIndex := strings.LastIndex(service, "}") + 1
|
|
||||||
var firstServiceIndex int
|
|
||||||
for index, char := range service {
|
|
||||||
if !isSpace(char) && !isNewline(char) {
|
|
||||||
firstServiceIndex = index
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
if line == ")" && parseInfo {
|
||||||
|
parseInfo = false
|
||||||
|
result.Info = segment + ")"
|
||||||
|
segment = ""
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(line, "import") {
|
||||||
|
parseImport = true
|
||||||
|
}
|
||||||
|
if parseImport && (strings.HasPrefix(line, "type") || strings.HasPrefix(line, "@server") ||
|
||||||
|
strings.HasPrefix(line, "service")) {
|
||||||
|
parseImport = false
|
||||||
|
result.Imports = segment
|
||||||
|
segment = line + "\n"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(line, "type") {
|
||||||
|
parseType = true
|
||||||
|
}
|
||||||
|
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"
|
||||||
}
|
}
|
||||||
service = service[firstServiceIndex:lastServiceRightBraceIndex]
|
|
||||||
return
|
if !parseSevice {
|
||||||
|
return nil, errors.New("no service defined")
|
||||||
|
}
|
||||||
|
result.Service = segment
|
||||||
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user