瀏覽代碼

Fix Dart API generation bugs; Add ability to generate API for path parameters (#2887)

* Fix bug in dartgen: Import path should match the generated api filename

* Use Route.HandlerName as generated dart API function name

Reasons:
- There is bug when using url path name as function name, because it may have invalid characters such as ":"
- Switching to HandlerName aligns with other languages such as typescript generation

* [DartGen] Add ability to generate api for url path parameters such as /path/:param
fondoger 2 年之前
父節點
當前提交
5756627904
共有 3 個文件被更改,包括 65 次插入26 次删除
  1. 6 4
      tools/goctl/api/dartgen/genapi.go
  2. 49 15
      tools/goctl/api/dartgen/util.go
  3. 10 7
      tools/goctl/api/dartgen/vars.go

+ 6 - 4
tools/goctl/api/dartgen/genapi.go

@@ -30,19 +30,21 @@ Future {{pathToFuncName .Path}}( {{if ne .Method "get"}}{{with .RequestType}}{{.
 {{end}}`
 
 const apiTemplateV2 = `import 'api.dart';
-import '../data/{{with .Info}}{{getBaseName .Title}}{{end}}.dart';
+import '../data/{{with .Service}}{{.Name}}{{end}}.dart';
 {{with .Service}}
 /// {{.Name}}
-{{range .Routes}}
+{{range $i, $Route := .Routes}}
 /// --{{.Path}}--
 ///
 /// request: {{with .RequestType}}{{.Name}}{{end}}
 /// response: {{with .ResponseType}}{{.Name}}{{end}}
-Future {{pathToFuncName .Path}}( {{if ne .Method "get"}}{{with .RequestType}}{{.Name}} request,{{end}}{{end}}
+Future {{normalizeHandlerName .Handler}}( 
+	{{if hasUrlPathParams $Route}}{{extractPositionalParamsFromPath $Route}},{{end}}
+	{{if ne .Method "get"}}{{with .RequestType}}{{.Name}} request,{{end}}{{end}}
     {Function({{with .ResponseType}}{{.Name}}{{end}})? ok,
     Function(String)? fail,
     Function? eventually}) async {
-  await api{{if eq .Method "get"}}Get{{else}}Post{{end}}('{{.Path}}',{{if ne .Method "get"}}request,{{end}}
+  await api{{if eq .Method "get"}}Get{{else}}Post{{end}}({{makeDartRequestUrlPath $Route}},{{if ne .Method "get"}}request,{{end}}
   	 ok: (data) {
     if (ok != null) ok({{with .ResponseType}}{{.Name}}.fromJson(data){{end}});
   }, fail: fail, eventually: eventually);

+ 49 - 15
tools/goctl/api/dartgen/util.go

@@ -11,6 +11,18 @@ import (
 	"github.com/zeromicro/go-zero/tools/goctl/api/util"
 )
 
+const (
+	formTagKey   = "form"
+	pathTagKey   = "path"
+	headerTagKey = "header"
+)
+
+func normalizeHandlerName(handlerName string) string {
+	handler := strings.Replace(handlerName, "Handler", "", 1)
+	handler = lowCamelCase(handler)
+	return handler
+}
+
 func lowCamelCase(s string) string {
 	if len(s) < 1 {
 		return ""
@@ -20,21 +32,6 @@ func lowCamelCase(s string) string {
 	return util.ToLower(s[:1]) + s[1:]
 }
 
-func pathToFuncName(path string) string {
-	if !strings.HasPrefix(path, "/") {
-		path = "/" + path
-	}
-	if !strings.HasPrefix(path, "/api") {
-		path = "/api" + path
-	}
-
-	path = strings.Replace(path, "/", "_", -1)
-	path = strings.Replace(path, "-", "_", -1)
-
-	camel := util.ToCamelCase(path)
-	return util.ToLower(camel[:1]) + camel[1:]
-}
-
 func getBaseName(str string) string {
 	return path.Base(str)
 }
@@ -170,3 +167,40 @@ func primitiveType(tp string) (string, bool) {
 
 	return "", false
 }
+
+func hasUrlPathParams(route spec.Route) bool {
+	ds, ok := route.RequestType.(spec.DefineStruct)
+	if !ok {
+		return false
+	}
+
+	return len(route.RequestTypeName()) > 0 && len(ds.GetTagMembers(pathTagKey)) > 0
+}
+
+func extractPositionalParamsFromPath(route spec.Route) string {
+	ds, ok := route.RequestType.(spec.DefineStruct)
+	if !ok {
+		return ""
+	}
+
+	var params []string
+	for _, member := range ds.GetTagMembers(pathTagKey) {
+		params = append(params, fmt.Sprintf("%s %s", member.Type.Name(), getPropertyFromMember(member)))
+	}
+
+	return strings.Join(params, ", ")
+}
+
+func makeDartRequestUrlPath(route spec.Route) string {
+	path := route.Path
+	ds, ok := route.RequestType.(spec.DefineStruct)
+	if !ok {
+		return path
+	}
+
+	for _, member := range ds.GetTagMembers(pathTagKey) {
+		path = strings.ReplaceAll(path, ":"+pathTagKey, "${"+getPropertyFromMember(member)+"}")
+	}
+
+	return `"` + path + `"`
+}

+ 10 - 7
tools/goctl/api/dartgen/vars.go

@@ -3,13 +3,16 @@ package dartgen
 import "text/template"
 
 var funcMap = template.FuncMap{
-	"getBaseName":           getBaseName,
-	"getPropertyFromMember": getPropertyFromMember,
-	"isDirectType":          isDirectType,
-	"isClassListType":       isClassListType,
-	"getCoreType":           getCoreType,
-	"pathToFuncName":        pathToFuncName,
-	"lowCamelCase":          lowCamelCase,
+	"getBaseName":                     getBaseName,
+	"getPropertyFromMember":           getPropertyFromMember,
+	"isDirectType":                    isDirectType,
+	"isClassListType":                 isClassListType,
+	"getCoreType":                     getCoreType,
+	"lowCamelCase":                    lowCamelCase,
+	"normalizeHandlerName":            normalizeHandlerName,
+	"hasUrlPathParams":                hasUrlPathParams,
+	"extractPositionalParamsFromPath": extractPositionalParamsFromPath,
+	"makeDartRequestUrlPath":          makeDartRequestUrlPath,
 }
 
 const (