add anonymous annotation (#134)

* 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

* support return ()

* revert

* refactor and rename folder to group

* remove no need

* add anonymous annotation

* optimized

* rename

* rename

* update test

* optimized new command

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

@ -65,7 +65,7 @@ func ApiFormat(path string, printToConsole bool) error {
return m
})
apiStruct, err := parser.MatchStruct(r)
apiStruct, err := parser.ParseApi(r)
if err != nil {
return err
}

@ -20,9 +20,7 @@ type Response struct {
}
service {{.name}}-api {
@server(
handler: GreetHandler
)
@handler GreetHandler
get /greet/from/:name(Request) returns (Response);
}
`

@ -84,6 +84,18 @@ memberLoop:
if builder.Len() == 0 {
return errors.New("invalid annotation format")
}
if len(annoName) > 0 {
value := builder.String()
if value != string(leftParenthesis) {
builder.Reset()
annos = append(annos, spec.Annotation{
Name: annoName,
Value: value,
})
annoName = ""
break annotationLoop
}
}
case next == leftParenthesis:
if builder.Len() == 0 {
return errors.New("invalid annotation format")
@ -101,6 +113,7 @@ memberLoop:
Name: annoName,
Properties: attrs,
})
annoName = ""
break annotationLoop
default:
builder.WriteRune(next)

@ -16,6 +16,7 @@ import (
type Parser struct {
r *bufio.Reader
typeDef string
api *ApiStruct
}
func NewParser(filename string) (*Parser, error) {
@ -29,7 +30,7 @@ func NewParser(filename string) (*Parser, error) {
return nil, err
}
apiStruct, err := MatchStruct(string(api))
apiStruct, err := ParseApi(string(api))
if err != nil {
return nil, err
}
@ -55,6 +56,7 @@ func NewParser(filename string) (*Parser, error) {
return &Parser{
r: bufio.NewReader(buffer),
typeDef: apiStruct.StructBody,
api: apiStruct,
}, nil
}
@ -66,7 +68,7 @@ func (p *Parser) Parse() (api *spec.ApiSpec, err error) {
return nil, err
}
api.Types = types
var lineNumber = 1
var lineNumber = p.api.serviceBeginLine
st := newRootState(p.r, &lineNumber)
for {
st, err = st.process(api)

@ -104,6 +104,21 @@ service A-api
}
`
const anonymousAnnotation = `
type Request struct {
Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
}
type Response struct {
Message string ` + "`" + `json:"message"` + "`" + `
}
service A-api {
@handler GreetHandler
get /greet/from/:name(Request) returns (Response)
}
`
func TestParser(t *testing.T) {
filename := "greet.api"
err := ioutil.WriteFile(filename, []byte(testApiTemplate), os.ModePerm)
@ -161,6 +176,25 @@ func TestInvalidApiFile(t *testing.T) {
assert.Nil(t, err)
defer os.Remove(filename)
_, err = NewParser(filename)
parser, err := NewParser(filename)
assert.Nil(t, err)
_, err = parser.Parse()
assert.NotNil(t, err)
}
func TestAnonymousAnnotation(t *testing.T) {
filename := "greet.api"
err := ioutil.WriteFile(filename, []byte(anonymousAnnotation), os.ModePerm)
assert.Nil(t, err)
defer os.Remove(filename)
parser, err := NewParser(filename)
assert.Nil(t, err)
api, err := parser.Parse()
assert.Nil(t, err)
assert.Equal(t, len(api.Service.Routes), 1)
assert.Equal(t, api.Service.Routes[0].Annotations[0].Value, "GreetHandler")
}

@ -11,10 +11,11 @@ import (
var emptyType spec.Type
type ApiStruct struct {
Info string
StructBody string
Service string
Imports string
Info string
StructBody string
Service string
Imports string
serviceBeginLine int
}
func GetType(api *spec.ApiSpec, t string) spec.Type {
@ -69,7 +70,7 @@ func unread(r *bufio.Reader) error {
return r.UnreadRune()
}
func MatchStruct(api string) (*ApiStruct, error) {
func ParseApi(api string) (*ApiStruct, error) {
var result ApiStruct
scanner := bufio.NewScanner(strings.NewReader(api))
var parseInfo = false
@ -104,13 +105,13 @@ func MatchStruct(api string) (*ApiStruct, error) {
parseType = true
}
if isServiceBeginLine(line) {
parseService = true
if parseType {
parseType = false
result.StructBody = segment
segment = line + "\n"
continue
}
parseService = true
}
segment += scanner.Text() + "\n"
}
@ -119,6 +120,7 @@ func MatchStruct(api string) (*ApiStruct, error) {
return nil, errors.New("no service defined")
}
result.Service = segment
result.serviceBeginLine = lineBeginOfService(api)
return &result, nil
}
@ -133,3 +135,16 @@ func isTypeBeginLine(line string) bool {
func isServiceBeginLine(line string) bool {
return strings.HasPrefix(line, "@server(") || (strings.HasPrefix(line, "service") && strings.HasSuffix(line, "{"))
}
func lineBeginOfService(api string) int {
scanner := bufio.NewScanner(strings.NewReader(api))
var number = 0
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if isServiceBeginLine(line) {
break
}
number++
}
return number
}

@ -4,6 +4,7 @@ type (
Annotation struct {
Name string
Properties map[string]string
Value string
}
ApiSpec struct {

@ -8,6 +8,9 @@ import (
func GetAnnotationValue(annos []spec.Annotation, key, field string) (string, bool) {
for _, anno := range annos {
if anno.Name == field && len(anno.Value) > 0 {
return anno.Value, true
}
if anno.Name == key {
value, ok := anno.Properties[field]
return strings.TrimSpace(value), ok

Loading…
Cancel
Save