mirror of
https://github.com/beego/bee.git
synced 2024-12-24 13:10:49 +00:00
commit
f728b23527
@ -1,8 +1,6 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.6.3
|
||||
- 1.7.3
|
||||
- 1.8
|
||||
- 1.10.3
|
||||
install:
|
||||
- export PATH=$PATH:$HOME/gopath/bin
|
||||
- go get -u github.com/opennota/check/cmd/structcheck
|
||||
|
3
Beefile
3
Beefile
@ -1,6 +1,7 @@
|
||||
version: 0
|
||||
go_install: false
|
||||
watch_ext: []
|
||||
watch_ext: [".go"]
|
||||
watch_ext_static: [".html", ".tpl", ".js", ".css"]
|
||||
dir_structure:
|
||||
watch_all: false
|
||||
controllers: ""
|
||||
|
@ -4,7 +4,8 @@ bee
|
||||
|
||||
Bee is a command-line tool facilitating development of Beego-based application.
|
||||
|
||||
[![Build Status](https://drone.io/github.com/beego/bee/status.png)](https://drone.io/github.com/beego/bee/latest)
|
||||
[![Build Status](https://img.shields.io/travis/beego/bee.svg?branch=master&label=master)](https://travis-ci.org/beego/bee)
|
||||
[![Build Status](https://img.shields.io/travis/beego/bee.svg?branch=develop&label=develop)](https://travis-ci.org/beego/bee)
|
||||
|
||||
## Requirements
|
||||
|
||||
|
3
bee.json
3
bee.json
@ -1,7 +1,8 @@
|
||||
{
|
||||
"version": 0,
|
||||
"go_install": false,
|
||||
"watch_ext": [],
|
||||
"watch_ext": [".go"],
|
||||
"watch_ext_static": [".html", ".tpl", ".js", ".css"],
|
||||
"dir_structure": {
|
||||
"watch_all": false,
|
||||
"controllers": "",
|
||||
|
@ -166,6 +166,7 @@ func appCode(cmd *commands.Command, args []string, currpath string) {
|
||||
beeLogger.Log.Infof("Using '%s' as 'Level'", generate.Level)
|
||||
generate.GenerateAppcode(generate.SQLDriver.String(), generate.SQLConn.String(), generate.Level.String(), generate.Tables.String(), currpath)
|
||||
}
|
||||
|
||||
func migration(cmd *commands.Command, args []string, currpath string) {
|
||||
if len(args) < 2 {
|
||||
beeLogger.Log.Fatal("Wrong number of arguments. Run: bee help generate")
|
||||
|
@ -196,6 +196,17 @@ func checkForSchemaUpdateTable(db *sql.DB, driver string) {
|
||||
}
|
||||
}
|
||||
|
||||
func driverImportStatement(driver string) string {
|
||||
switch driver {
|
||||
case "mysql":
|
||||
return "github.com/go-sql-driver/mysql"
|
||||
case "postgres":
|
||||
return "github.com/lib/pq"
|
||||
default:
|
||||
return "github.com/go-sql-driver/mysql"
|
||||
}
|
||||
}
|
||||
|
||||
func showMigrationsTableSQL(driver string) string {
|
||||
switch driver {
|
||||
case "mysql":
|
||||
@ -263,6 +274,7 @@ func writeMigrationSourceFile(dir, source, driver, connStr string, latestTime in
|
||||
beeLogger.Log.Fatalf("Could not create file: %s", err)
|
||||
} else {
|
||||
content := strings.Replace(MigrationMainTPL, "{{DBDriver}}", driver, -1)
|
||||
content = strings.Replace(content, "{{DriverRepo}}", driverImportStatement(driver), -1)
|
||||
content = strings.Replace(content, "{{ConnStr}}", connStr, -1)
|
||||
content = strings.Replace(content, "{{LatestTime}}", strconv.FormatInt(latestTime, 10), -1)
|
||||
content = strings.Replace(content, "{{LatestName}}", latestName, -1)
|
||||
@ -346,8 +358,7 @@ import(
|
||||
"github.com/astaxie/beego/orm"
|
||||
"github.com/astaxie/beego/migration"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/lib/pq"
|
||||
_ "{{DriverRepo}}"
|
||||
)
|
||||
|
||||
func init(){
|
||||
|
@ -58,6 +58,8 @@ var (
|
||||
currentGoPath string
|
||||
// Current runmode
|
||||
runmode string
|
||||
// Extra args to run application
|
||||
runargs string
|
||||
// Extra directories
|
||||
extraPackages utils.StrFlags
|
||||
)
|
||||
@ -71,6 +73,7 @@ func init() {
|
||||
CmdRun.Flag.BoolVar(&vendorWatch, "vendor", false, "Enable watch vendor folder.")
|
||||
CmdRun.Flag.StringVar(&buildTags, "tags", "", "Set the build tags. See: https://golang.org/pkg/go/build/")
|
||||
CmdRun.Flag.StringVar(&runmode, "runmode", "", "Set the Beego run mode.")
|
||||
CmdRun.Flag.StringVar(&runargs, "runargs", "", "Extra args to run application")
|
||||
CmdRun.Flag.Var(&extraPackages, "ex", "List of extra package to watch.")
|
||||
exit = make(chan bool)
|
||||
commands.AvailableCommands = append(commands.AvailableCommands, CmdRun)
|
||||
|
@ -36,13 +36,14 @@ var (
|
||||
state sync.Mutex
|
||||
eventTime = make(map[string]int64)
|
||||
scheduleTime time.Time
|
||||
watchExts = []string{".go"}
|
||||
watchExtsStatic = []string{".html", ".tpl", ".js", ".css"}
|
||||
watchExts = config.Conf.WatchExts
|
||||
watchExtsStatic = config.Conf.WatchExtsStatic
|
||||
ignoredFilesRegExps = []string{
|
||||
`.#(\w+).go`,
|
||||
`.(\w+).go.swp`,
|
||||
`(\w+).go~`,
|
||||
`(\w+).tmp`,
|
||||
`commentsRouter_controllers.go`,
|
||||
}
|
||||
)
|
||||
|
||||
@ -86,6 +87,12 @@ func NewWatcher(paths []string, files []string, isgenerate bool) {
|
||||
scheduleTime = time.Now().Add(1 * time.Second)
|
||||
time.Sleep(scheduleTime.Sub(time.Now()))
|
||||
AutoBuild(files, isgenerate)
|
||||
|
||||
if config.Conf.EnableReload {
|
||||
// Wait 100ms more before refreshing the browser
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
sendReload(e.String())
|
||||
}
|
||||
}()
|
||||
}
|
||||
case err := <-watcher.Errors:
|
||||
@ -139,9 +146,9 @@ func AutoBuild(files []string, isgenerate bool) {
|
||||
}
|
||||
beeLogger.Log.Success("Docs generated!")
|
||||
}
|
||||
|
||||
appName := appname
|
||||
if err == nil {
|
||||
appName := appname
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
appName += ".exe"
|
||||
}
|
||||
@ -165,7 +172,7 @@ func AutoBuild(files []string, isgenerate bool) {
|
||||
}
|
||||
|
||||
beeLogger.Log.Success("Built Successfully!")
|
||||
Restart(appname)
|
||||
Restart(appName)
|
||||
}
|
||||
|
||||
// Kill kills the running command process
|
||||
@ -200,7 +207,13 @@ func Start(appname string) {
|
||||
cmd = exec.Command(appname)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Args = append([]string{appname}, config.Conf.CmdArgs...)
|
||||
if runargs != "" {
|
||||
r := regexp.MustCompile("'.+'|\".+\"|\\S+")
|
||||
m := r.FindAllString(runargs, -1)
|
||||
cmd.Args = append([]string{appname}, m...)
|
||||
} else {
|
||||
cmd.Args = append([]string{appname}, config.Conf.CmdArgs...)
|
||||
}
|
||||
cmd.Env = append(os.Environ(), config.Conf.Envs...)
|
||||
|
||||
go cmd.Run()
|
||||
|
@ -57,7 +57,7 @@ Prints the current Bee, Beego and Go version alongside the platform information.
|
||||
}
|
||||
var outputFormat string
|
||||
|
||||
const version = "1.9.1"
|
||||
const version = "1.10.0"
|
||||
|
||||
func init() {
|
||||
fs := flag.NewFlagSet("version", flag.ContinueOnError)
|
||||
|
@ -27,6 +27,8 @@ const confVer = 0
|
||||
|
||||
var Conf = struct {
|
||||
Version int
|
||||
WatchExts []string `json:"watch_ext" yaml:"watch_ext"`
|
||||
WatchExtsStatic []string `json:"watch_ext_static" yaml:"watch_ext_static"`
|
||||
GoInstall bool `json:"go_install" yaml:"go_install"` // Indicates whether execute "go install" before "go build".
|
||||
DirStruct dirStruct `json:"dir_structure" yaml:"dir_structure"`
|
||||
CmdArgs []string `json:"cmd_args" yaml:"cmd_args"`
|
||||
@ -37,7 +39,9 @@ var Conf = struct {
|
||||
EnableNotification bool `json:"enable_notification" yaml:"enable_notification"`
|
||||
Scripts map[string]string `json:"scripts" yaml:"scripts"`
|
||||
}{
|
||||
GoInstall: true,
|
||||
WatchExts: []string{".go"},
|
||||
WatchExtsStatic: []string{".html", ".tpl", ".js", ".css"},
|
||||
GoInstall: true,
|
||||
DirStruct: dirStruct{
|
||||
Others: []string{},
|
||||
},
|
||||
|
@ -318,7 +318,7 @@ func gen(dbms, connStr string, mode byte, selectedTableNames map[string]bool, ap
|
||||
mvcPath.RouterPath = path.Join(apppath, "routers")
|
||||
createPaths(mode, mvcPath)
|
||||
pkgPath := getPackagePath(apppath)
|
||||
writeSourceFiles(pkgPath, tables, mode, mvcPath, selectedTableNames)
|
||||
writeSourceFiles(pkgPath, tables, mode, mvcPath)
|
||||
} else {
|
||||
beeLogger.Log.Fatalf("Generating app code from '%s' database is not supported yet.", dbms)
|
||||
}
|
||||
@ -728,32 +728,26 @@ func createPaths(mode byte, paths *MvcPath) {
|
||||
// writeSourceFiles generates source files for model/controller/router
|
||||
// It will wipe the following directories and recreate them:./models, ./controllers, ./routers
|
||||
// Newly geneated files will be inside these folders.
|
||||
func writeSourceFiles(pkgPath string, tables []*Table, mode byte, paths *MvcPath, selectedTables map[string]bool) {
|
||||
func writeSourceFiles(pkgPath string, tables []*Table, mode byte, paths *MvcPath) {
|
||||
if (OModel & mode) == OModel {
|
||||
beeLogger.Log.Info("Creating model files...")
|
||||
writeModelFiles(tables, paths.ModelPath, selectedTables)
|
||||
writeModelFiles(tables, paths.ModelPath)
|
||||
}
|
||||
if (OController & mode) == OController {
|
||||
beeLogger.Log.Info("Creating controller files...")
|
||||
writeControllerFiles(tables, paths.ControllerPath, selectedTables, pkgPath)
|
||||
writeControllerFiles(tables, paths.ControllerPath, pkgPath)
|
||||
}
|
||||
if (ORouter & mode) == ORouter {
|
||||
beeLogger.Log.Info("Creating router files...")
|
||||
writeRouterFile(tables, paths.RouterPath, selectedTables, pkgPath)
|
||||
writeRouterFile(tables, paths.RouterPath, pkgPath)
|
||||
}
|
||||
}
|
||||
|
||||
// writeModelFiles generates model files
|
||||
func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bool) {
|
||||
func writeModelFiles(tables []*Table, mPath string) {
|
||||
w := colors.NewColorWriter(os.Stdout)
|
||||
|
||||
for _, tb := range tables {
|
||||
// if selectedTables map is not nil and this table is not selected, ignore it
|
||||
if selectedTables != nil {
|
||||
if _, selected := selectedTables[tb.Name]; !selected {
|
||||
continue
|
||||
}
|
||||
}
|
||||
filename := getFileName(tb.Name)
|
||||
fpath := path.Join(mPath, filename+".go")
|
||||
var f *os.File
|
||||
@ -806,16 +800,10 @@ func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bo
|
||||
}
|
||||
|
||||
// writeControllerFiles generates controller files
|
||||
func writeControllerFiles(tables []*Table, cPath string, selectedTables map[string]bool, pkgPath string) {
|
||||
func writeControllerFiles(tables []*Table, cPath string, pkgPath string) {
|
||||
w := colors.NewColorWriter(os.Stdout)
|
||||
|
||||
for _, tb := range tables {
|
||||
// If selectedTables map is not nil and this table is not selected, ignore it
|
||||
if selectedTables != nil {
|
||||
if _, selected := selectedTables[tb.Name]; !selected {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if tb.Pk == "" {
|
||||
continue
|
||||
}
|
||||
@ -854,17 +842,11 @@ func writeControllerFiles(tables []*Table, cPath string, selectedTables map[stri
|
||||
}
|
||||
|
||||
// writeRouterFile generates router file
|
||||
func writeRouterFile(tables []*Table, rPath string, selectedTables map[string]bool, pkgPath string) {
|
||||
func writeRouterFile(tables []*Table, rPath string, pkgPath string) {
|
||||
w := colors.NewColorWriter(os.Stdout)
|
||||
|
||||
var nameSpaces []string
|
||||
for _, tb := range tables {
|
||||
// If selectedTables map is not nil and this table is not selected, ignore it
|
||||
if selectedTables != nil {
|
||||
if _, selected := selectedTables[tb.Name]; !selected {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if tb.Pk == "" {
|
||||
continue
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"reflect"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
@ -77,7 +78,7 @@ var basicTypes = map[string]string{
|
||||
"byte": "string:byte",
|
||||
"rune": "string:byte",
|
||||
// builtin golang objects
|
||||
"time.Time": "string:string",
|
||||
"time.Time": "string:datetime",
|
||||
}
|
||||
|
||||
var stdlibObject = map[string]string{
|
||||
@ -93,6 +94,7 @@ func init() {
|
||||
astPkgs = make([]*ast.Package, 0)
|
||||
}
|
||||
|
||||
// ParsePackagesFromDir parses packages from a given directory
|
||||
func ParsePackagesFromDir(dirpath string) {
|
||||
c := make(chan error)
|
||||
|
||||
@ -105,11 +107,12 @@ func ParsePackagesFromDir(dirpath string) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 7 is length of 'vendor' (6) + length of file path separator (1)
|
||||
// so we skip dir 'vendor' which is directly under dirpath
|
||||
if !(len(fpath) == len(dirpath)+7 && strings.HasSuffix(fpath, "vendor")) &&
|
||||
// skip folder if it's a 'vendor' folder within dirpath or its child,
|
||||
// all 'tests' folders and dot folders wihin dirpath
|
||||
d, _ := filepath.Rel(dirpath, fpath)
|
||||
if !(d == "vendor" || strings.HasPrefix(d, "vendor"+string(os.PathSeparator))) &&
|
||||
!strings.Contains(fpath, "tests") &&
|
||||
!(len(fpath) > len(dirpath) && fpath[len(dirpath)+1] == '.') {
|
||||
!(d[0] == '.') {
|
||||
err = parsePackageFromDir(fpath)
|
||||
if err != nil {
|
||||
// Send the error to through the channel and continue walking
|
||||
@ -144,6 +147,7 @@ func parsePackageFromDir(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenerateDocs generates documentations for a given path.
|
||||
func GenerateDocs(curpath string) {
|
||||
fset := token.NewFileSet()
|
||||
|
||||
@ -261,8 +265,9 @@ func GenerateDocs(curpath string) {
|
||||
case *ast.AssignStmt:
|
||||
for _, l := range stmt.Rhs {
|
||||
if v, ok := l.(*ast.CallExpr); ok {
|
||||
// Analyse NewNamespace, it will return version and the subfunction
|
||||
if selName := v.Fun.(*ast.SelectorExpr).Sel.String(); selName != "NewNamespace" {
|
||||
// Analyze NewNamespace, it will return version and the subfunction
|
||||
selExpr, selOK := v.Fun.(*ast.SelectorExpr)
|
||||
if !selOK || selExpr.Sel.Name != "NewNamespace" {
|
||||
continue
|
||||
}
|
||||
version, params := analyseNewNamespace(v)
|
||||
@ -348,21 +353,21 @@ func analyseNewNamespace(ce *ast.CallExpr) (first string, others []ast.Expr) {
|
||||
func analyseNSInclude(baseurl string, ce *ast.CallExpr) string {
|
||||
cname := ""
|
||||
for _, p := range ce.Args {
|
||||
var x *ast.SelectorExpr
|
||||
var p1 interface{} = p
|
||||
if ident, ok := p1.(*ast.Ident); ok {
|
||||
if assign, ok := ident.Obj.Decl.(*ast.AssignStmt); ok {
|
||||
if len(assign.Rhs) > 0 {
|
||||
p1 = assign.Rhs[0].(*ast.UnaryExpr)
|
||||
}
|
||||
}
|
||||
}
|
||||
if _, ok := p1.(*ast.UnaryExpr); ok {
|
||||
x = p1.(*ast.UnaryExpr).X.(*ast.CompositeLit).Type.(*ast.SelectorExpr)
|
||||
} else {
|
||||
beeLogger.Log.Warnf("Couldn't determine type\n")
|
||||
continue
|
||||
}
|
||||
var x *ast.SelectorExpr
|
||||
var p1 interface{} = p
|
||||
if ident, ok := p1.(*ast.Ident); ok {
|
||||
if assign, ok := ident.Obj.Decl.(*ast.AssignStmt); ok {
|
||||
if len(assign.Rhs) > 0 {
|
||||
p1 = assign.Rhs[0].(*ast.UnaryExpr)
|
||||
}
|
||||
}
|
||||
}
|
||||
if _, ok := p1.(*ast.UnaryExpr); ok {
|
||||
x = p1.(*ast.UnaryExpr).X.(*ast.CompositeLit).Type.(*ast.SelectorExpr)
|
||||
} else {
|
||||
beeLogger.Log.Warnf("Couldn't determine type\n")
|
||||
continue
|
||||
}
|
||||
if v, ok := importlist[fmt.Sprint(x.X)]; ok {
|
||||
cname = v + x.Sel.Name
|
||||
}
|
||||
@ -627,10 +632,25 @@ func parserComments(f *ast.FuncDecl, controllerName, pkgpath string) error {
|
||||
pp := strings.Split(p[2], ".")
|
||||
typ := pp[len(pp)-1]
|
||||
if len(pp) >= 2 {
|
||||
m, mod, realTypes := getModel(p[2])
|
||||
para.Schema = &swagger.Schema{
|
||||
Ref: "#/definitions/" + m,
|
||||
isArray := false
|
||||
if p[1] == "body" && strings.HasPrefix(p[2], "[]") {
|
||||
p[2] = p[2][2:]
|
||||
isArray = true
|
||||
}
|
||||
m, mod, realTypes := getModel(p[2])
|
||||
if isArray {
|
||||
para.Schema = &swagger.Schema{
|
||||
Type: "array",
|
||||
Items: &swagger.Schema{
|
||||
Ref: "#/definitions/" + m,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
para.Schema = &swagger.Schema{
|
||||
Ref: "#/definitions/" + m,
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := modelsList[pkgpath+controllerName]; !ok {
|
||||
modelsList[pkgpath+controllerName] = make(map[string]swagger.Schema)
|
||||
}
|
||||
@ -779,10 +799,20 @@ func setParamType(para *swagger.Parameter, typ string, pkgpath, controllerName s
|
||||
appendModels(pkgpath, controllerName, realTypes)
|
||||
}
|
||||
if isArray {
|
||||
para.Type = "array"
|
||||
para.Items = &swagger.ParameterItems{
|
||||
Type: paraType,
|
||||
Format: paraFormat,
|
||||
if para.In == "body" {
|
||||
para.Schema = &swagger.Schema{
|
||||
Type: "array",
|
||||
Items: &swagger.Schema{
|
||||
Type: paraType,
|
||||
Format: paraFormat,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
para.Type = "array"
|
||||
para.Items = &swagger.ParameterItems{
|
||||
Type: paraType,
|
||||
Format: paraFormat,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
para.Type = paraType
|
||||
@ -910,10 +940,111 @@ func parseObject(d *ast.Object, k string, m *swagger.Schema, realTypes *[]string
|
||||
beeLogger.Log.Fatalf("Unknown type without TypeSec: %v\n", d)
|
||||
}
|
||||
// TODO support other types, such as `ArrayType`, `MapType`, `InterfaceType` etc...
|
||||
st, ok := ts.Type.(*ast.StructType)
|
||||
if !ok {
|
||||
return
|
||||
switch t := ts.Type.(type) {
|
||||
case *ast.ArrayType:
|
||||
m.Title = k
|
||||
m.Type = "array"
|
||||
if isBasicType(fmt.Sprint(t.Elt)) {
|
||||
typeFormat := strings.Split(basicTypes[fmt.Sprint(t.Elt)], ":")
|
||||
m.Format = typeFormat[0]
|
||||
} else {
|
||||
objectName := packageName + "." + fmt.Sprint(t.Elt)
|
||||
if _, ok := rootapi.Definitions[objectName]; !ok {
|
||||
objectName, _, _ = getModel(objectName)
|
||||
}
|
||||
m.Items = &swagger.Schema{
|
||||
Ref: "#/definitions/" + objectName,
|
||||
}
|
||||
}
|
||||
case *ast.Ident:
|
||||
parseIdent(t, k, m, astPkgs)
|
||||
case *ast.StructType:
|
||||
parseStruct(t, k, m, realTypes, astPkgs, packageName)
|
||||
}
|
||||
}
|
||||
|
||||
// parse as enum, in the package, find out all consts with the same type
|
||||
func parseIdent(st *ast.Ident, k string, m *swagger.Schema, astPkgs []*ast.Package) {
|
||||
m.Title = k
|
||||
basicType := fmt.Sprint(st)
|
||||
if object, isStdLibObject := stdlibObject[basicType]; isStdLibObject {
|
||||
basicType = object
|
||||
}
|
||||
if k, ok := basicTypes[basicType]; ok {
|
||||
typeFormat := strings.Split(k, ":")
|
||||
m.Type = typeFormat[0]
|
||||
m.Format = typeFormat[1]
|
||||
}
|
||||
enums := make(map[int]string)
|
||||
enumValues := make(map[int]interface{})
|
||||
for _, pkg := range astPkgs {
|
||||
for _, fl := range pkg.Files {
|
||||
for _, obj := range fl.Scope.Objects {
|
||||
if obj.Kind == ast.Con {
|
||||
vs, ok := obj.Decl.(*ast.ValueSpec)
|
||||
if !ok {
|
||||
beeLogger.Log.Fatalf("Unknown type without ValueSpec: %v\n", vs)
|
||||
}
|
||||
|
||||
ti, ok := vs.Type.(*ast.Ident)
|
||||
if !ok {
|
||||
// TODO type inference, iota not support yet
|
||||
continue
|
||||
}
|
||||
// Only add the enums that are defined by the current identifier
|
||||
if ti.Name != k {
|
||||
continue
|
||||
}
|
||||
|
||||
// For all names and values, aggregate them by it's position so that we can sort them later.
|
||||
for i, val := range vs.Values {
|
||||
v, ok := val.(*ast.BasicLit)
|
||||
if !ok {
|
||||
beeLogger.Log.Warnf("Unknown type without BasicLit: %v\n", v)
|
||||
continue
|
||||
}
|
||||
enums[int(val.Pos())] = fmt.Sprintf("%s = %s", vs.Names[i].Name, v.Value)
|
||||
switch v.Kind {
|
||||
case token.INT:
|
||||
vv, err := strconv.Atoi(v.Value)
|
||||
if err != nil {
|
||||
beeLogger.Log.Warnf("Unknown type with BasicLit to int: %v\n", v.Value)
|
||||
continue
|
||||
}
|
||||
enumValues[int(val.Pos())] = vv
|
||||
case token.FLOAT:
|
||||
vv, err := strconv.ParseFloat(v.Value, 64)
|
||||
if err != nil {
|
||||
beeLogger.Log.Warnf("Unknown type with BasicLit to int: %v\n", v.Value)
|
||||
continue
|
||||
}
|
||||
enumValues[int(val.Pos())] = vv
|
||||
default:
|
||||
enumValues[int(val.Pos())] = strings.Trim(v.Value, `"`)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Sort the enums by position
|
||||
if len(enums) > 0 {
|
||||
var keys []int
|
||||
for k := range enums {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Ints(keys)
|
||||
for _, k := range keys {
|
||||
m.Enum = append(m.Enum, enums[k])
|
||||
}
|
||||
// Automatically use the first enum value as the example.
|
||||
m.Example = enumValues[keys[0]]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func parseStruct(st *ast.StructType, k string, m *swagger.Schema, realTypes *[]string, astPkgs []*ast.Package, packageName string) {
|
||||
m.Title = k
|
||||
if st.Fields.List != nil {
|
||||
m.Properties = make(map[string]swagger.Propertie)
|
||||
@ -931,9 +1062,10 @@ func parseObject(d *ast.Object, k string, m *swagger.Schema, realTypes *[]string
|
||||
}
|
||||
*realTypes = append(*realTypes, realType)
|
||||
mp := swagger.Propertie{}
|
||||
isObject := false
|
||||
if isSlice {
|
||||
mp.Type = "array"
|
||||
if isBasicType(strings.Replace(realType, "[]", "", -1)) {
|
||||
if sType, ok := basicTypes[(strings.Replace(realType, "[]", "", -1))]; ok {
|
||||
typeFormat := strings.Split(sType, ":")
|
||||
mp.Items = &swagger.Propertie{
|
||||
Type: typeFormat[0],
|
||||
@ -946,6 +1078,7 @@ func parseObject(d *ast.Object, k string, m *swagger.Schema, realTypes *[]string
|
||||
}
|
||||
} else {
|
||||
if sType == "object" {
|
||||
isObject = true
|
||||
mp.Ref = "#/definitions/" + realType
|
||||
} else if isBasicType(realType) {
|
||||
typeFormat := strings.Split(sType, ":")
|
||||
@ -1013,20 +1146,50 @@ func parseObject(d *ast.Object, k string, m *swagger.Schema, realTypes *[]string
|
||||
mp.Description = desc
|
||||
}
|
||||
|
||||
if example := stag.Get("example"); example != "" && !isObject && !isSlice {
|
||||
mp.Example = str2RealType(example, realType)
|
||||
}
|
||||
|
||||
m.Properties[name] = mp
|
||||
}
|
||||
if ignore := stag.Get("ignore"); ignore != "" {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
for _, pkg := range astPkgs {
|
||||
for _, fl := range pkg.Files {
|
||||
for nameOfObj, obj := range fl.Scope.Objects {
|
||||
if obj.Name == fmt.Sprint(field.Type) {
|
||||
parseObject(obj, nameOfObj, m, realTypes, astPkgs, pkg.Name)
|
||||
// only parse case of when embedded field is TypeName
|
||||
// cases of *TypeName and Interface are not handled, maybe useless for swagger spec
|
||||
tag := ""
|
||||
if field.Tag != nil {
|
||||
stag := reflect.StructTag(strings.Trim(field.Tag.Value, "`"))
|
||||
tag = stag.Get("json")
|
||||
}
|
||||
|
||||
if tag != "" {
|
||||
tagValues := strings.Split(tag, ",")
|
||||
if tagValues[0] == "-" {
|
||||
//if json tag is "-", omit
|
||||
continue
|
||||
} else {
|
||||
//if json tag is "something", output: something #definition/pkgname.Type
|
||||
m.Properties[tagValues[0]] = mp
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
//if no json tag, expand all fields of the type here
|
||||
nm := &swagger.Schema{}
|
||||
for _, pkg := range astPkgs {
|
||||
for _, fl := range pkg.Files {
|
||||
for nameOfObj, obj := range fl.Scope.Objects {
|
||||
if obj.Name == fmt.Sprint(field.Type) {
|
||||
parseObject(obj, nameOfObj, nm, realTypes, astPkgs, pkg.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for name, p := range nm.Properties {
|
||||
m.Properties[name] = p
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1049,6 +1212,9 @@ func typeAnalyser(f *ast.Field) (isSlice bool, realType, swaggerType string) {
|
||||
switch t := f.Type.(type) {
|
||||
case *ast.StarExpr:
|
||||
basicType := fmt.Sprint(t.X)
|
||||
if object, isStdLibObject := stdlibObject[basicType]; isStdLibObject {
|
||||
basicType = object
|
||||
}
|
||||
if k, ok := basicTypes[basicType]; ok {
|
||||
return false, basicType, k
|
||||
}
|
||||
@ -1114,6 +1280,12 @@ func urlReplace(src string) string {
|
||||
} else if p[0] == '?' && p[1] == ':' {
|
||||
pt[i] = "{" + p[2:] + "}"
|
||||
}
|
||||
|
||||
if pt[i][0] == '{' && strings.Contains(pt[i], ":") {
|
||||
pt[i] = pt[i][:strings.Index(pt[i], ":")] + "}"
|
||||
} else if pt[i][0] == '{' && strings.Contains(pt[i], "(") {
|
||||
pt[i] = pt[i][:strings.Index(pt[i], "(")] + "}"
|
||||
}
|
||||
}
|
||||
}
|
||||
return strings.Join(pt, "/")
|
||||
@ -1126,6 +1298,8 @@ func str2RealType(s string, typ string) interface{} {
|
||||
switch typ {
|
||||
case "int", "int64", "int32", "int16", "int8":
|
||||
ret, err = strconv.Atoi(s)
|
||||
case "uint", "uint64", "uint32", "uint16", "uint8":
|
||||
ret, err = strconv.ParseUint(s, 10, 0)
|
||||
case "bool":
|
||||
ret, err = strconv.ParseBool(s)
|
||||
case "float64":
|
||||
|
9
main.go
9
main.go
@ -25,9 +25,15 @@ import (
|
||||
"github.com/beego/bee/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
workspace = os.Getenv("BeeWorkspace")
|
||||
)
|
||||
|
||||
func main() {
|
||||
currentpath, _ := os.Getwd()
|
||||
|
||||
if workspace != "" {
|
||||
currentpath = workspace
|
||||
}
|
||||
flag.Usage = cmd.Usage
|
||||
flag.Parse()
|
||||
log.SetFlags(0)
|
||||
@ -66,7 +72,6 @@ func main() {
|
||||
if utils.IsInGOPATH(currentpath) && cmd.IfGenerateDocs(c.Name(), args) {
|
||||
swaggergen.ParsePackagesFromDir(currentpath)
|
||||
}
|
||||
|
||||
os.Exit(c.Run(c, args))
|
||||
return
|
||||
}
|
||||
|
13
vendor/github.com/astaxie/beego/LICENSE
generated
vendored
13
vendor/github.com/astaxie/beego/LICENSE
generated
vendored
@ -1,13 +0,0 @@
|
||||
Copyright 2014 astaxie
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
4
vendor/github.com/astaxie/beego/swagger/swagger.go
generated
vendored
4
vendor/github.com/astaxie/beego/swagger/swagger.go
generated
vendored
@ -121,6 +121,8 @@ type Schema struct {
|
||||
Type string `json:"type,omitempty" yaml:"type,omitempty"`
|
||||
Items *Schema `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
Properties map[string]Propertie `json:"properties,omitempty" yaml:"properties,omitempty"`
|
||||
Enum []interface{} `json:"enum,omitempty" yaml:"enum,omitempty"`
|
||||
Example interface{} `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
}
|
||||
|
||||
// Propertie are taken from the JSON Schema definition but their definitions were adjusted to the Swagger Specification
|
||||
@ -130,7 +132,7 @@ type Propertie struct {
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Default interface{} `json:"default,omitempty" yaml:"default,omitempty"`
|
||||
Type string `json:"type,omitempty" yaml:"type,omitempty"`
|
||||
Example string `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Example interface{} `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Required []string `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Format string `json:"format,omitempty" yaml:"format,omitempty"`
|
||||
ReadOnly bool `json:"readOnly,omitempty" yaml:"readOnly,omitempty"`
|
||||
|
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
@ -3,10 +3,10 @@
|
||||
"ignore": "test",
|
||||
"package": [
|
||||
{
|
||||
"checksumSHA1": "OeOvZ+3A1tRBdMD8GuS6R9zcnqA=",
|
||||
"checksumSHA1": "/ffb74fNK251iTEebGjybfFBAbs=",
|
||||
"path": "github.com/astaxie/beego/swagger",
|
||||
"revision": "323a1c4214101331a4b71922c23d19b7409ac71f",
|
||||
"revisionTime": "2017-03-06T13:59:04Z"
|
||||
"revision": "a09bafbf2ab483742b17bb352f95dbc0a597e720",
|
||||
"revisionTime": "2018-07-21T07:55:28Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "epd3Y7nD7QVzTW0ppwK+q4pKo/4=",
|
||||
|
Loading…
Reference in New Issue
Block a user