mirror of
https://github.com/beego/bee.git
synced 2024-11-24 03:20:55 +00:00
commit
f728b23527
@ -1,8 +1,6 @@
|
|||||||
language: go
|
language: go
|
||||||
go:
|
go:
|
||||||
- 1.6.3
|
- 1.10.3
|
||||||
- 1.7.3
|
|
||||||
- 1.8
|
|
||||||
install:
|
install:
|
||||||
- export PATH=$PATH:$HOME/gopath/bin
|
- export PATH=$PATH:$HOME/gopath/bin
|
||||||
- go get -u github.com/opennota/check/cmd/structcheck
|
- go get -u github.com/opennota/check/cmd/structcheck
|
||||||
|
3
Beefile
3
Beefile
@ -1,6 +1,7 @@
|
|||||||
version: 0
|
version: 0
|
||||||
go_install: false
|
go_install: false
|
||||||
watch_ext: []
|
watch_ext: [".go"]
|
||||||
|
watch_ext_static: [".html", ".tpl", ".js", ".css"]
|
||||||
dir_structure:
|
dir_structure:
|
||||||
watch_all: false
|
watch_all: false
|
||||||
controllers: ""
|
controllers: ""
|
||||||
|
@ -4,7 +4,8 @@ bee
|
|||||||
|
|
||||||
Bee is a command-line tool facilitating development of Beego-based application.
|
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
|
## Requirements
|
||||||
|
|
||||||
|
3
bee.json
3
bee.json
@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"version": 0,
|
"version": 0,
|
||||||
"go_install": false,
|
"go_install": false,
|
||||||
"watch_ext": [],
|
"watch_ext": [".go"],
|
||||||
|
"watch_ext_static": [".html", ".tpl", ".js", ".css"],
|
||||||
"dir_structure": {
|
"dir_structure": {
|
||||||
"watch_all": false,
|
"watch_all": false,
|
||||||
"controllers": "",
|
"controllers": "",
|
||||||
|
@ -166,6 +166,7 @@ func appCode(cmd *commands.Command, args []string, currpath string) {
|
|||||||
beeLogger.Log.Infof("Using '%s' as 'Level'", generate.Level)
|
beeLogger.Log.Infof("Using '%s' as 'Level'", generate.Level)
|
||||||
generate.GenerateAppcode(generate.SQLDriver.String(), generate.SQLConn.String(), generate.Level.String(), generate.Tables.String(), currpath)
|
generate.GenerateAppcode(generate.SQLDriver.String(), generate.SQLConn.String(), generate.Level.String(), generate.Tables.String(), currpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func migration(cmd *commands.Command, args []string, currpath string) {
|
func migration(cmd *commands.Command, args []string, currpath string) {
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
beeLogger.Log.Fatal("Wrong number of arguments. Run: bee help generate")
|
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 {
|
func showMigrationsTableSQL(driver string) string {
|
||||||
switch driver {
|
switch driver {
|
||||||
case "mysql":
|
case "mysql":
|
||||||
@ -263,6 +274,7 @@ func writeMigrationSourceFile(dir, source, driver, connStr string, latestTime in
|
|||||||
beeLogger.Log.Fatalf("Could not create file: %s", err)
|
beeLogger.Log.Fatalf("Could not create file: %s", err)
|
||||||
} else {
|
} else {
|
||||||
content := strings.Replace(MigrationMainTPL, "{{DBDriver}}", driver, -1)
|
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, "{{ConnStr}}", connStr, -1)
|
||||||
content = strings.Replace(content, "{{LatestTime}}", strconv.FormatInt(latestTime, 10), -1)
|
content = strings.Replace(content, "{{LatestTime}}", strconv.FormatInt(latestTime, 10), -1)
|
||||||
content = strings.Replace(content, "{{LatestName}}", latestName, -1)
|
content = strings.Replace(content, "{{LatestName}}", latestName, -1)
|
||||||
@ -346,8 +358,7 @@ import(
|
|||||||
"github.com/astaxie/beego/orm"
|
"github.com/astaxie/beego/orm"
|
||||||
"github.com/astaxie/beego/migration"
|
"github.com/astaxie/beego/migration"
|
||||||
|
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "{{DriverRepo}}"
|
||||||
_ "github.com/lib/pq"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init(){
|
func init(){
|
||||||
|
@ -58,6 +58,8 @@ var (
|
|||||||
currentGoPath string
|
currentGoPath string
|
||||||
// Current runmode
|
// Current runmode
|
||||||
runmode string
|
runmode string
|
||||||
|
// Extra args to run application
|
||||||
|
runargs string
|
||||||
// Extra directories
|
// Extra directories
|
||||||
extraPackages utils.StrFlags
|
extraPackages utils.StrFlags
|
||||||
)
|
)
|
||||||
@ -71,6 +73,7 @@ func init() {
|
|||||||
CmdRun.Flag.BoolVar(&vendorWatch, "vendor", false, "Enable watch vendor folder.")
|
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(&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(&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.")
|
CmdRun.Flag.Var(&extraPackages, "ex", "List of extra package to watch.")
|
||||||
exit = make(chan bool)
|
exit = make(chan bool)
|
||||||
commands.AvailableCommands = append(commands.AvailableCommands, CmdRun)
|
commands.AvailableCommands = append(commands.AvailableCommands, CmdRun)
|
||||||
|
@ -36,13 +36,14 @@ var (
|
|||||||
state sync.Mutex
|
state sync.Mutex
|
||||||
eventTime = make(map[string]int64)
|
eventTime = make(map[string]int64)
|
||||||
scheduleTime time.Time
|
scheduleTime time.Time
|
||||||
watchExts = []string{".go"}
|
watchExts = config.Conf.WatchExts
|
||||||
watchExtsStatic = []string{".html", ".tpl", ".js", ".css"}
|
watchExtsStatic = config.Conf.WatchExtsStatic
|
||||||
ignoredFilesRegExps = []string{
|
ignoredFilesRegExps = []string{
|
||||||
`.#(\w+).go`,
|
`.#(\w+).go`,
|
||||||
`.(\w+).go.swp`,
|
`.(\w+).go.swp`,
|
||||||
`(\w+).go~`,
|
`(\w+).go~`,
|
||||||
`(\w+).tmp`,
|
`(\w+).tmp`,
|
||||||
|
`commentsRouter_controllers.go`,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -86,6 +87,12 @@ func NewWatcher(paths []string, files []string, isgenerate bool) {
|
|||||||
scheduleTime = time.Now().Add(1 * time.Second)
|
scheduleTime = time.Now().Add(1 * time.Second)
|
||||||
time.Sleep(scheduleTime.Sub(time.Now()))
|
time.Sleep(scheduleTime.Sub(time.Now()))
|
||||||
AutoBuild(files, isgenerate)
|
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:
|
case err := <-watcher.Errors:
|
||||||
@ -139,9 +146,9 @@ func AutoBuild(files []string, isgenerate bool) {
|
|||||||
}
|
}
|
||||||
beeLogger.Log.Success("Docs generated!")
|
beeLogger.Log.Success("Docs generated!")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
appName := appname
|
appName := appname
|
||||||
|
if err == nil {
|
||||||
|
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
appName += ".exe"
|
appName += ".exe"
|
||||||
}
|
}
|
||||||
@ -165,7 +172,7 @@ func AutoBuild(files []string, isgenerate bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
beeLogger.Log.Success("Built Successfully!")
|
beeLogger.Log.Success("Built Successfully!")
|
||||||
Restart(appname)
|
Restart(appName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kill kills the running command process
|
// Kill kills the running command process
|
||||||
@ -200,7 +207,13 @@ func Start(appname string) {
|
|||||||
cmd = exec.Command(appname)
|
cmd = exec.Command(appname)
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
|
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.Args = append([]string{appname}, config.Conf.CmdArgs...)
|
||||||
|
}
|
||||||
cmd.Env = append(os.Environ(), config.Conf.Envs...)
|
cmd.Env = append(os.Environ(), config.Conf.Envs...)
|
||||||
|
|
||||||
go cmd.Run()
|
go cmd.Run()
|
||||||
|
@ -57,7 +57,7 @@ Prints the current Bee, Beego and Go version alongside the platform information.
|
|||||||
}
|
}
|
||||||
var outputFormat string
|
var outputFormat string
|
||||||
|
|
||||||
const version = "1.9.1"
|
const version = "1.10.0"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
fs := flag.NewFlagSet("version", flag.ContinueOnError)
|
fs := flag.NewFlagSet("version", flag.ContinueOnError)
|
||||||
|
@ -27,6 +27,8 @@ const confVer = 0
|
|||||||
|
|
||||||
var Conf = struct {
|
var Conf = struct {
|
||||||
Version int
|
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".
|
GoInstall bool `json:"go_install" yaml:"go_install"` // Indicates whether execute "go install" before "go build".
|
||||||
DirStruct dirStruct `json:"dir_structure" yaml:"dir_structure"`
|
DirStruct dirStruct `json:"dir_structure" yaml:"dir_structure"`
|
||||||
CmdArgs []string `json:"cmd_args" yaml:"cmd_args"`
|
CmdArgs []string `json:"cmd_args" yaml:"cmd_args"`
|
||||||
@ -37,6 +39,8 @@ var Conf = struct {
|
|||||||
EnableNotification bool `json:"enable_notification" yaml:"enable_notification"`
|
EnableNotification bool `json:"enable_notification" yaml:"enable_notification"`
|
||||||
Scripts map[string]string `json:"scripts" yaml:"scripts"`
|
Scripts map[string]string `json:"scripts" yaml:"scripts"`
|
||||||
}{
|
}{
|
||||||
|
WatchExts: []string{".go"},
|
||||||
|
WatchExtsStatic: []string{".html", ".tpl", ".js", ".css"},
|
||||||
GoInstall: true,
|
GoInstall: true,
|
||||||
DirStruct: dirStruct{
|
DirStruct: dirStruct{
|
||||||
Others: []string{},
|
Others: []string{},
|
||||||
|
@ -318,7 +318,7 @@ func gen(dbms, connStr string, mode byte, selectedTableNames map[string]bool, ap
|
|||||||
mvcPath.RouterPath = path.Join(apppath, "routers")
|
mvcPath.RouterPath = path.Join(apppath, "routers")
|
||||||
createPaths(mode, mvcPath)
|
createPaths(mode, mvcPath)
|
||||||
pkgPath := getPackagePath(apppath)
|
pkgPath := getPackagePath(apppath)
|
||||||
writeSourceFiles(pkgPath, tables, mode, mvcPath, selectedTableNames)
|
writeSourceFiles(pkgPath, tables, mode, mvcPath)
|
||||||
} else {
|
} else {
|
||||||
beeLogger.Log.Fatalf("Generating app code from '%s' database is not supported yet.", dbms)
|
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
|
// writeSourceFiles generates source files for model/controller/router
|
||||||
// It will wipe the following directories and recreate them:./models, ./controllers, ./routers
|
// It will wipe the following directories and recreate them:./models, ./controllers, ./routers
|
||||||
// Newly geneated files will be inside these folders.
|
// 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 {
|
if (OModel & mode) == OModel {
|
||||||
beeLogger.Log.Info("Creating model files...")
|
beeLogger.Log.Info("Creating model files...")
|
||||||
writeModelFiles(tables, paths.ModelPath, selectedTables)
|
writeModelFiles(tables, paths.ModelPath)
|
||||||
}
|
}
|
||||||
if (OController & mode) == OController {
|
if (OController & mode) == OController {
|
||||||
beeLogger.Log.Info("Creating controller files...")
|
beeLogger.Log.Info("Creating controller files...")
|
||||||
writeControllerFiles(tables, paths.ControllerPath, selectedTables, pkgPath)
|
writeControllerFiles(tables, paths.ControllerPath, pkgPath)
|
||||||
}
|
}
|
||||||
if (ORouter & mode) == ORouter {
|
if (ORouter & mode) == ORouter {
|
||||||
beeLogger.Log.Info("Creating router files...")
|
beeLogger.Log.Info("Creating router files...")
|
||||||
writeRouterFile(tables, paths.RouterPath, selectedTables, pkgPath)
|
writeRouterFile(tables, paths.RouterPath, pkgPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeModelFiles generates model files
|
// 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)
|
w := colors.NewColorWriter(os.Stdout)
|
||||||
|
|
||||||
for _, tb := range tables {
|
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)
|
filename := getFileName(tb.Name)
|
||||||
fpath := path.Join(mPath, filename+".go")
|
fpath := path.Join(mPath, filename+".go")
|
||||||
var f *os.File
|
var f *os.File
|
||||||
@ -806,16 +800,10 @@ func writeModelFiles(tables []*Table, mPath string, selectedTables map[string]bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// writeControllerFiles generates controller files
|
// 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)
|
w := colors.NewColorWriter(os.Stdout)
|
||||||
|
|
||||||
for _, tb := range tables {
|
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 == "" {
|
if tb.Pk == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -854,17 +842,11 @@ func writeControllerFiles(tables []*Table, cPath string, selectedTables map[stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
// writeRouterFile generates router file
|
// 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)
|
w := colors.NewColorWriter(os.Stdout)
|
||||||
|
|
||||||
var nameSpaces []string
|
var nameSpaces []string
|
||||||
for _, tb := range tables {
|
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 == "" {
|
if tb.Pk == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
@ -77,7 +78,7 @@ var basicTypes = map[string]string{
|
|||||||
"byte": "string:byte",
|
"byte": "string:byte",
|
||||||
"rune": "string:byte",
|
"rune": "string:byte",
|
||||||
// builtin golang objects
|
// builtin golang objects
|
||||||
"time.Time": "string:string",
|
"time.Time": "string:datetime",
|
||||||
}
|
}
|
||||||
|
|
||||||
var stdlibObject = map[string]string{
|
var stdlibObject = map[string]string{
|
||||||
@ -93,6 +94,7 @@ func init() {
|
|||||||
astPkgs = make([]*ast.Package, 0)
|
astPkgs = make([]*ast.Package, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParsePackagesFromDir parses packages from a given directory
|
||||||
func ParsePackagesFromDir(dirpath string) {
|
func ParsePackagesFromDir(dirpath string) {
|
||||||
c := make(chan error)
|
c := make(chan error)
|
||||||
|
|
||||||
@ -105,11 +107,12 @@ func ParsePackagesFromDir(dirpath string) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7 is length of 'vendor' (6) + length of file path separator (1)
|
// skip folder if it's a 'vendor' folder within dirpath or its child,
|
||||||
// so we skip dir 'vendor' which is directly under dirpath
|
// all 'tests' folders and dot folders wihin dirpath
|
||||||
if !(len(fpath) == len(dirpath)+7 && strings.HasSuffix(fpath, "vendor")) &&
|
d, _ := filepath.Rel(dirpath, fpath)
|
||||||
|
if !(d == "vendor" || strings.HasPrefix(d, "vendor"+string(os.PathSeparator))) &&
|
||||||
!strings.Contains(fpath, "tests") &&
|
!strings.Contains(fpath, "tests") &&
|
||||||
!(len(fpath) > len(dirpath) && fpath[len(dirpath)+1] == '.') {
|
!(d[0] == '.') {
|
||||||
err = parsePackageFromDir(fpath)
|
err = parsePackageFromDir(fpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Send the error to through the channel and continue walking
|
// Send the error to through the channel and continue walking
|
||||||
@ -144,6 +147,7 @@ func parsePackageFromDir(path string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateDocs generates documentations for a given path.
|
||||||
func GenerateDocs(curpath string) {
|
func GenerateDocs(curpath string) {
|
||||||
fset := token.NewFileSet()
|
fset := token.NewFileSet()
|
||||||
|
|
||||||
@ -261,8 +265,9 @@ func GenerateDocs(curpath string) {
|
|||||||
case *ast.AssignStmt:
|
case *ast.AssignStmt:
|
||||||
for _, l := range stmt.Rhs {
|
for _, l := range stmt.Rhs {
|
||||||
if v, ok := l.(*ast.CallExpr); ok {
|
if v, ok := l.(*ast.CallExpr); ok {
|
||||||
// Analyse NewNamespace, it will return version and the subfunction
|
// Analyze NewNamespace, it will return version and the subfunction
|
||||||
if selName := v.Fun.(*ast.SelectorExpr).Sel.String(); selName != "NewNamespace" {
|
selExpr, selOK := v.Fun.(*ast.SelectorExpr)
|
||||||
|
if !selOK || selExpr.Sel.Name != "NewNamespace" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
version, params := analyseNewNamespace(v)
|
version, params := analyseNewNamespace(v)
|
||||||
@ -627,10 +632,25 @@ func parserComments(f *ast.FuncDecl, controllerName, pkgpath string) error {
|
|||||||
pp := strings.Split(p[2], ".")
|
pp := strings.Split(p[2], ".")
|
||||||
typ := pp[len(pp)-1]
|
typ := pp[len(pp)-1]
|
||||||
if len(pp) >= 2 {
|
if len(pp) >= 2 {
|
||||||
|
isArray := false
|
||||||
|
if p[1] == "body" && strings.HasPrefix(p[2], "[]") {
|
||||||
|
p[2] = p[2][2:]
|
||||||
|
isArray = true
|
||||||
|
}
|
||||||
m, mod, realTypes := getModel(p[2])
|
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{
|
para.Schema = &swagger.Schema{
|
||||||
Ref: "#/definitions/" + m,
|
Ref: "#/definitions/" + m,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if _, ok := modelsList[pkgpath+controllerName]; !ok {
|
if _, ok := modelsList[pkgpath+controllerName]; !ok {
|
||||||
modelsList[pkgpath+controllerName] = make(map[string]swagger.Schema)
|
modelsList[pkgpath+controllerName] = make(map[string]swagger.Schema)
|
||||||
}
|
}
|
||||||
@ -779,11 +799,21 @@ func setParamType(para *swagger.Parameter, typ string, pkgpath, controllerName s
|
|||||||
appendModels(pkgpath, controllerName, realTypes)
|
appendModels(pkgpath, controllerName, realTypes)
|
||||||
}
|
}
|
||||||
if isArray {
|
if isArray {
|
||||||
|
if para.In == "body" {
|
||||||
|
para.Schema = &swagger.Schema{
|
||||||
|
Type: "array",
|
||||||
|
Items: &swagger.Schema{
|
||||||
|
Type: paraType,
|
||||||
|
Format: paraFormat,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
para.Type = "array"
|
para.Type = "array"
|
||||||
para.Items = &swagger.ParameterItems{
|
para.Items = &swagger.ParameterItems{
|
||||||
Type: paraType,
|
Type: paraType,
|
||||||
Format: paraFormat,
|
Format: paraFormat,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
para.Type = paraType
|
para.Type = paraType
|
||||||
para.Format = paraFormat
|
para.Format = paraFormat
|
||||||
@ -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)
|
beeLogger.Log.Fatalf("Unknown type without TypeSec: %v\n", d)
|
||||||
}
|
}
|
||||||
// TODO support other types, such as `ArrayType`, `MapType`, `InterfaceType` etc...
|
// TODO support other types, such as `ArrayType`, `MapType`, `InterfaceType` etc...
|
||||||
st, ok := ts.Type.(*ast.StructType)
|
switch t := ts.Type.(type) {
|
||||||
if !ok {
|
case *ast.ArrayType:
|
||||||
return
|
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
|
m.Title = k
|
||||||
if st.Fields.List != nil {
|
if st.Fields.List != nil {
|
||||||
m.Properties = make(map[string]swagger.Propertie)
|
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)
|
*realTypes = append(*realTypes, realType)
|
||||||
mp := swagger.Propertie{}
|
mp := swagger.Propertie{}
|
||||||
|
isObject := false
|
||||||
if isSlice {
|
if isSlice {
|
||||||
mp.Type = "array"
|
mp.Type = "array"
|
||||||
if isBasicType(strings.Replace(realType, "[]", "", -1)) {
|
if sType, ok := basicTypes[(strings.Replace(realType, "[]", "", -1))]; ok {
|
||||||
typeFormat := strings.Split(sType, ":")
|
typeFormat := strings.Split(sType, ":")
|
||||||
mp.Items = &swagger.Propertie{
|
mp.Items = &swagger.Propertie{
|
||||||
Type: typeFormat[0],
|
Type: typeFormat[0],
|
||||||
@ -946,6 +1078,7 @@ func parseObject(d *ast.Object, k string, m *swagger.Schema, realTypes *[]string
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if sType == "object" {
|
if sType == "object" {
|
||||||
|
isObject = true
|
||||||
mp.Ref = "#/definitions/" + realType
|
mp.Ref = "#/definitions/" + realType
|
||||||
} else if isBasicType(realType) {
|
} else if isBasicType(realType) {
|
||||||
typeFormat := strings.Split(sType, ":")
|
typeFormat := strings.Split(sType, ":")
|
||||||
@ -1013,21 +1146,51 @@ func parseObject(d *ast.Object, k string, m *swagger.Schema, realTypes *[]string
|
|||||||
mp.Description = desc
|
mp.Description = desc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if example := stag.Get("example"); example != "" && !isObject && !isSlice {
|
||||||
|
mp.Example = str2RealType(example, realType)
|
||||||
|
}
|
||||||
|
|
||||||
m.Properties[name] = mp
|
m.Properties[name] = mp
|
||||||
}
|
}
|
||||||
if ignore := stag.Get("ignore"); ignore != "" {
|
if ignore := stag.Get("ignore"); ignore != "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// 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 _, pkg := range astPkgs {
|
||||||
for _, fl := range pkg.Files {
|
for _, fl := range pkg.Files {
|
||||||
for nameOfObj, obj := range fl.Scope.Objects {
|
for nameOfObj, obj := range fl.Scope.Objects {
|
||||||
if obj.Name == fmt.Sprint(field.Type) {
|
if obj.Name == fmt.Sprint(field.Type) {
|
||||||
parseObject(obj, nameOfObj, m, realTypes, astPkgs, pkg.Name)
|
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) {
|
switch t := f.Type.(type) {
|
||||||
case *ast.StarExpr:
|
case *ast.StarExpr:
|
||||||
basicType := fmt.Sprint(t.X)
|
basicType := fmt.Sprint(t.X)
|
||||||
|
if object, isStdLibObject := stdlibObject[basicType]; isStdLibObject {
|
||||||
|
basicType = object
|
||||||
|
}
|
||||||
if k, ok := basicTypes[basicType]; ok {
|
if k, ok := basicTypes[basicType]; ok {
|
||||||
return false, basicType, k
|
return false, basicType, k
|
||||||
}
|
}
|
||||||
@ -1114,6 +1280,12 @@ func urlReplace(src string) string {
|
|||||||
} else if p[0] == '?' && p[1] == ':' {
|
} else if p[0] == '?' && p[1] == ':' {
|
||||||
pt[i] = "{" + p[2:] + "}"
|
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, "/")
|
return strings.Join(pt, "/")
|
||||||
@ -1126,6 +1298,8 @@ func str2RealType(s string, typ string) interface{} {
|
|||||||
switch typ {
|
switch typ {
|
||||||
case "int", "int64", "int32", "int16", "int8":
|
case "int", "int64", "int32", "int16", "int8":
|
||||||
ret, err = strconv.Atoi(s)
|
ret, err = strconv.Atoi(s)
|
||||||
|
case "uint", "uint64", "uint32", "uint16", "uint8":
|
||||||
|
ret, err = strconv.ParseUint(s, 10, 0)
|
||||||
case "bool":
|
case "bool":
|
||||||
ret, err = strconv.ParseBool(s)
|
ret, err = strconv.ParseBool(s)
|
||||||
case "float64":
|
case "float64":
|
||||||
|
9
main.go
9
main.go
@ -25,9 +25,15 @@ import (
|
|||||||
"github.com/beego/bee/utils"
|
"github.com/beego/bee/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
workspace = os.Getenv("BeeWorkspace")
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
currentpath, _ := os.Getwd()
|
currentpath, _ := os.Getwd()
|
||||||
|
if workspace != "" {
|
||||||
|
currentpath = workspace
|
||||||
|
}
|
||||||
flag.Usage = cmd.Usage
|
flag.Usage = cmd.Usage
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
@ -66,7 +72,6 @@ func main() {
|
|||||||
if utils.IsInGOPATH(currentpath) && cmd.IfGenerateDocs(c.Name(), args) {
|
if utils.IsInGOPATH(currentpath) && cmd.IfGenerateDocs(c.Name(), args) {
|
||||||
swaggergen.ParsePackagesFromDir(currentpath)
|
swaggergen.ParsePackagesFromDir(currentpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Exit(c.Run(c, args))
|
os.Exit(c.Run(c, args))
|
||||||
return
|
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"`
|
Type string `json:"type,omitempty" yaml:"type,omitempty"`
|
||||||
Items *Schema `json:"items,omitempty" yaml:"items,omitempty"`
|
Items *Schema `json:"items,omitempty" yaml:"items,omitempty"`
|
||||||
Properties map[string]Propertie `json:"properties,omitempty" yaml:"properties,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
|
// 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"`
|
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||||
Default interface{} `json:"default,omitempty" yaml:"default,omitempty"`
|
Default interface{} `json:"default,omitempty" yaml:"default,omitempty"`
|
||||||
Type string `json:"type,omitempty" yaml:"type,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"`
|
Required []string `json:"required,omitempty" yaml:"required,omitempty"`
|
||||||
Format string `json:"format,omitempty" yaml:"format,omitempty"`
|
Format string `json:"format,omitempty" yaml:"format,omitempty"`
|
||||||
ReadOnly bool `json:"readOnly,omitempty" yaml:"readOnly,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",
|
"ignore": "test",
|
||||||
"package": [
|
"package": [
|
||||||
{
|
{
|
||||||
"checksumSHA1": "OeOvZ+3A1tRBdMD8GuS6R9zcnqA=",
|
"checksumSHA1": "/ffb74fNK251iTEebGjybfFBAbs=",
|
||||||
"path": "github.com/astaxie/beego/swagger",
|
"path": "github.com/astaxie/beego/swagger",
|
||||||
"revision": "323a1c4214101331a4b71922c23d19b7409ac71f",
|
"revision": "a09bafbf2ab483742b17bb352f95dbc0a597e720",
|
||||||
"revisionTime": "2017-03-06T13:59:04Z"
|
"revisionTime": "2018-07-21T07:55:28Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "epd3Y7nD7QVzTW0ppwK+q4pKo/4=",
|
"checksumSHA1": "epd3Y7nD7QVzTW0ppwK+q4pKo/4=",
|
||||||
|
Loading…
Reference in New Issue
Block a user