Skip to content

Commit

Permalink
refactor(gen.go): improve code coverage (#468)
Browse files Browse the repository at this point in the history
* Fix issue #467
Fix issue #466
Refactor gen/gen.go , improve gen.go coverage

* Rollback #466 , backtick will be escaped .

* Fix tests
  • Loading branch information
ubogdan authored and easonlin404 committed Jul 20, 2019
1 parent be88a64 commit 67075e4
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 31 deletions.
142 changes: 115 additions & 27 deletions gen/gen.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package gen

import (
"bytes"
"encoding/json"
"fmt"
"github.com/go-openapi/spec"
"go/format"
"io"
"log"
"os"
"path"
Expand All @@ -16,8 +20,7 @@ import (
)

// Gen presents a generate tool for swag.
type Gen struct {
}
type Gen struct{}

// New creates a new Gen.
func New() *Gen {
Expand Down Expand Up @@ -65,12 +68,7 @@ func (g *Gen) Build(config *Config) error {
}
swagger := p.GetSwagger()

schemes := []string{}
for _, scheme := range swagger.Schemes {
schemes = append(schemes, fmt.Sprintf("%q", scheme))
}

b, err := json.MarshalIndent(swagger, "", " ")
b, err := g.jsonIndent(swagger)
if err != nil {
return err
}
Expand All @@ -89,8 +87,8 @@ func (g *Gen) Build(config *Config) error {
if err != nil {
return err
}

defer swaggerJSON.Close()

if _, err := swaggerJSON.Write(b); err != nil {
return err
}
Expand All @@ -110,32 +108,115 @@ func (g *Gen) Build(config *Config) error {
return err
}

swagger.Schemes = []string{}
b, err = json.MarshalIndent(swagger, "", " ")
// Write doc
err = g.writeGoDoc(docs, swagger)
if err != nil {
return err
}

if err := packageTemplate.Execute(docs, struct {
Timestamp time.Time
Doc string
Schemes string
}{
Timestamp: time.Now(),
Doc: "`" + strings.Replace(string(b), "{", "{\n \"schemes\": {{ marshal .Schemes }},", 1) + "`",
Schemes: "[]string{" + strings.Join(schemes, ",") + "}",
}); err != nil {
return err
}

log.Printf("create docs.go at %+v", docs.Name())
log.Printf("create swagger.json at %+v", swaggerJSON.Name())
log.Printf("create swagger.yaml at %+v", swaggerYAML.Name())

return nil
}

var packageTemplate = template.Must(template.New("").Parse(`// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
func (g *Gen) jsonIndent(data interface{}) ([]byte, error) {
return json.MarshalIndent(data, "", " ")
}

func (g *Gen) formatSource(src []byte) []byte {
code, err := format.Source(src)
if err != nil {
code = src // Output the unformated code anyway
}
return code
}

func (g *Gen) writeGoDoc(output io.Writer, swagger *spec.Swagger) error {

generator, err := template.New("swagger_info").Funcs(template.FuncMap{
"printDoc": func(v string) string {
// Add schemes
v = "{\n \"schemes\": {{ marshal .Schemes }}," + v[1:]
// Sanitize backticks
return strings.Replace(v, "`", "`+\"`\"+`", -1)
},
}).Parse(packageTemplate)
if err != nil {
return err
}

swaggerSpec := &spec.Swagger{
VendorExtensible: swagger.VendorExtensible,
SwaggerProps: spec.SwaggerProps{
ID: swagger.ID,
Consumes: swagger.Consumes,
Produces: swagger.Produces,
Swagger: swagger.Swagger,
Info: &spec.Info{
VendorExtensible: swagger.Info.VendorExtensible,
InfoProps: spec.InfoProps{
Description: "{{.Description}}",
Title: "{{.Title}}",
TermsOfService: swagger.Info.TermsOfService,
Contact: swagger.Info.Contact,
License: swagger.Info.License,
Version: "{{.Version}}",
},
},
Host: "{{.Host}}",
BasePath: "{{.BasePath}}",
Paths: swagger.Paths,
Definitions: swagger.Definitions,
Parameters: swagger.Parameters,
Responses: swagger.Responses,
SecurityDefinitions: swagger.SecurityDefinitions,
Security: swagger.Security,
Tags: swagger.Tags,
ExternalDocs: swagger.ExternalDocs,
},
}

// crafted docs.json
buf, err := g.jsonIndent(swaggerSpec)
if err != nil {
return err
}

buffer := &bytes.Buffer{}
err = generator.Execute(buffer, struct {
Timestamp time.Time
Doc string
Host string
BasePath string
Schemes []string
Title string
Description string
Version string
}{
Timestamp: time.Now(),
Doc: string(buf),
Host: swagger.Host,
BasePath: swagger.BasePath,
Schemes: swagger.Schemes,
Title: swagger.Info.Title,
Description: swagger.Info.Description,
Version: swagger.Info.Version,
})
if err != nil {
return err
}

code := g.formatSource(buffer.Bytes())

// write
_, err = output.Write(code)
return err

}

var packageTemplate = `// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// This file was generated by swaggo/swag at
// {{ .Timestamp }}
Expand All @@ -149,7 +230,7 @@ import (
"github.com/swaggo/swag"
)
var doc = {{.Doc}}
var doc = ` + "`{{ printDoc .Doc}}`" + `
type swaggerInfo struct {
Version string
Expand All @@ -161,7 +242,14 @@ type swaggerInfo struct {
}
// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = swaggerInfo{Schemes: {{.Schemes}}}
var SwaggerInfo = swaggerInfo{
Version: {{ printf "%q" .Version}},
Host: {{ printf "%q" .Host}},
BasePath: {{ printf "%q" .BasePath}},
Schemes: []string{ {{ range $index, $schema := .Schemes}}{{if gt $index 0}},{{end}}{{printf "%q" $schema}}{{end}} },
Title: {{ printf "%q" .Title}},
Description: {{ printf "%q" .Description}},
}
type s struct{}
Expand All @@ -187,4 +275,4 @@ func (s *s) ReadDoc() string {
func init() {
swag.Register(swag.Name, &s{})
}
`))
`
55 changes: 55 additions & 0 deletions gen/gen_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gen

import (
"github.com/go-openapi/spec"
"os"
"path"
"path/filepath"
Expand Down Expand Up @@ -164,6 +165,7 @@ func TestGen_FailToWrite(t *testing.T) {
if err != nil {
t.Fatal(err)
}

}

func TestGen_configWithOutputDir(t *testing.T) {
Expand All @@ -190,3 +192,56 @@ func TestGen_configWithOutputDir(t *testing.T) {

//TODO: remove gen files
}

func TestGen_formatSource(t *testing.T) {
src := `package main
import "net
func main() {}
`
g := New()

res := g.formatSource([]byte(src))
assert.Equal(t, []byte(src), res, "Should return same content due to fmt fail")

src2 := `package main
import "fmt"
func main() {
fmt.Print("Helo world")
}
`
res = g.formatSource([]byte(src2))
assert.NotEqual(t, []byte(src2), res, "Should return fmt code")
}

type mocWriter struct{}

func (w *mocWriter) Write(data []byte) (int, error) {
return len(data), nil
}

func TestGen_writeGoDoc(t *testing.T) {
gen := New()

swapTemplate := packageTemplate

packageTemplate = `{{{`
err := gen.writeGoDoc(nil, nil)
assert.Error(t, err)

packageTemplate = `{{.Data}}`
swagger := &spec.Swagger{
VendorExtensible: spec.VendorExtensible{},
SwaggerProps: spec.SwaggerProps{
Info: &spec.Info{},
},
}
err = gen.writeGoDoc(&mocWriter{}, swagger)
assert.Error(t, err)

packageTemplate = swapTemplate

}
10 changes: 8 additions & 2 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -843,10 +843,10 @@ func (parser *Parser) parseStruct(pkgName string, field *ast.Field) (map[string]
}
var desc string
if field.Doc != nil {
desc = strings.TrimSpace(strings.Replace(field.Doc.Text(), "`", "", -1))
desc = strings.TrimSpace(field.Doc.Text())
}
if desc == "" && field.Comment != nil {
desc = strings.TrimSpace(strings.Replace(field.Comment.Text(), "`", "", -1))
desc = strings.TrimSpace(field.Comment.Text())
}
// TODO: find package of schemaType and/or arrayType

Expand Down Expand Up @@ -1412,6 +1412,12 @@ func (parser *Parser) Skip(path string, f os.FileInfo) error {
return filepath.SkipDir
}
}

// issue
if f.IsDir() && f.Name() == "docs" {
return filepath.SkipDir
}

// exclude all hidden folder
if f.IsDir() && len(f.Name()) > 1 && f.Name()[0] == '.' {
return filepath.SkipDir
Expand Down
4 changes: 2 additions & 2 deletions parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1932,11 +1932,11 @@ func TestParseStructComment(t *testing.T) {
"type": "string"
},
"errorCtx": {
"description": "Error context tick comment",
"description": "Error ` + "`" + `context` + "`" + ` tick comment",
"type": "string"
},
"errorNo": {
"description": "Error number tick comment",
"description": "Error ` + "`" + `number` + "`" + ` tick comment",
"type": "integer"
}
}
Expand Down

0 comments on commit 67075e4

Please sign in to comment.