private/apigen: Resolve import issues

This change resolves several issues:
* Imports can no longer be duplicated
* The import statement now conforms to Storj's code style requirements
* Packages are imported as needed, eliminating extraneous imports

Change-Id: Ie021e06bb0d472c65aa3575db94bc81ccac108e3
This commit is contained in:
Jeremy Wharton 2022-06-08 23:12:50 -05:00 committed by Storj Robot
parent ffcd54719a
commit 905654956a

View File

@ -9,6 +9,7 @@ import (
"net/http"
"os"
"reflect"
"sort"
"strings"
"time"
@ -45,57 +46,55 @@ func (a *API) generateGo() ([]byte, error) {
return pathPackages[len(pathPackages)-1]
}
p("// AUTOGENERATED BY private/apigen")
p("// DO NOT EDIT.")
p("")
imports := struct {
All map[string]bool
Standard []string
External []string
Internal []string
}{
All: make(map[string]bool),
}
p("package %s", a.PackageName)
p("")
i := func(paths ...string) {
for _, path := range paths {
if getPackageName(path) == a.PackageName {
return
}
p("import (")
p(`"context"`)
p(`"encoding/json"`)
p(`"net/http"`)
p(`"time"`)
p("")
p(`"github.com/gorilla/mux"`)
p(`"github.com/zeebo/errs"`)
p(`"go.uber.org/zap"`)
p("")
if _, ok := imports.All[path]; ok {
return
}
imports.All[path] = true
p(`"storj.io/common/uuid"`)
p(`"storj.io/storj/private/api"`)
var slice *[]string
switch {
case !strings.Contains(path, "."):
slice = &imports.Standard
case strings.HasPrefix(path, "storj.io"):
slice = &imports.Internal
default:
slice = &imports.External
}
*slice = append(*slice, path)
}
}
for _, group := range a.EndpointGroups {
for _, method := range group.Endpoints {
if method.Request != nil {
path := reflect.TypeOf(method.Request).Elem().PkgPath()
pn := getPackageName(path)
if pn == a.PackageName {
continue
}
p(`"%s"`, path)
i(reflect.TypeOf(method.Request).Elem().PkgPath())
}
if method.Response != nil {
path := reflect.TypeOf(method.Response).Elem().PkgPath()
pn := getPackageName(path)
if pn == a.PackageName {
continue
}
p(`"%s"`, path)
i(reflect.TypeOf(method.Response).Elem().PkgPath())
}
}
}
p(")")
p("")
p("const dateLayout = \"2006-01-02T15:04:05.000Z\"")
p("")
for _, group := range a.EndpointGroups {
i("github.com/zeebo/errs")
p("var Err%sAPI = errs.Class(\"%s %s api\")", cases.Title(language.Und).String(group.Prefix), a.PackageName, group.Prefix)
}
@ -109,6 +108,7 @@ func (a *API) generateGo() ([]byte, error) {
params += param.Type.String() + ", "
}
i("context", "storj.io/storj/private/api")
if e.Response != nil {
responseType := reflect.TypeOf(e.Response)
p("%s(context.Context, "+params+") (%s, api.HTTPError)", e.MethodName, a.handleTypesPackage(responseType))
@ -121,6 +121,7 @@ func (a *API) generateGo() ([]byte, error) {
}
for _, group := range a.EndpointGroups {
i("go.uber.org/zap")
p("// %sHandler is an api handler that exposes all %s related functionality.", group.Name, group.Prefix)
p("type %sHandler struct {", group.Name)
p("log *zap.Logger")
@ -131,6 +132,7 @@ func (a *API) generateGo() ([]byte, error) {
}
for _, group := range a.EndpointGroups {
i("github.com/gorilla/mux")
p(
"func New%s(log *zap.Logger, service %sService, router *mux.Router, auth api.Auth) *%sHandler {",
group.Name,
@ -156,6 +158,7 @@ func (a *API) generateGo() ([]byte, error) {
for _, group := range a.EndpointGroups {
for pathMethod, endpoint := range group.Endpoints {
i("net/http")
p("")
handlerName := "handle" + endpoint.MethodName
p("func (h *%sHandler) %s(w http.ResponseWriter, r *http.Request) {", group.Name, handlerName)
@ -168,15 +171,7 @@ func (a *API) generateGo() ([]byte, error) {
p("")
if !endpoint.NoCookieAuth || !endpoint.NoAPIAuth {
if !endpoint.NoCookieAuth && !endpoint.NoAPIAuth {
p("ctx, err = h.auth.IsAuthenticated(ctx, r, true, true)")
}
if endpoint.NoCookieAuth && !endpoint.NoAPIAuth {
p("ctx, err = h.auth.IsAuthenticated(ctx, r, false, true)")
}
if !endpoint.NoCookieAuth && endpoint.NoAPIAuth {
p("ctx, err = h.auth.IsAuthenticated(ctx, r, true, false)")
}
p("ctx, err = h.auth.IsAuthenticated(ctx, r, %v, %v)", !endpoint.NoCookieAuth, !endpoint.NoAPIAuth)
p("if err != nil {")
if !endpoint.NoCookieAuth {
p("h.auth.RemoveAuthCookie(w)")
@ -192,9 +187,11 @@ func (a *API) generateGo() ([]byte, error) {
for _, param := range endpoint.Params {
switch param.Type {
case reflect.TypeOf(uuid.UUID{}):
i("storj.io/common/uuid")
handleUUIDQuery(p, param)
continue
case reflect.TypeOf(time.Time{}):
i("time")
handleTimeQuery(p, param)
continue
case reflect.TypeOf(""):
@ -262,6 +259,7 @@ func (a *API) generateGo() ([]byte, error) {
p("return")
p("}")
i("encoding/json")
p("")
p("err = json.NewEncoder(w).Encode(retVal)")
p("if err != nil {")
@ -271,6 +269,34 @@ func (a *API) generateGo() ([]byte, error) {
}
}
fileBody := result
result = ""
p("// AUTOGENERATED BY private/apigen")
p("// DO NOT EDIT.")
p("")
p("package %s", a.PackageName)
p("")
p("import (")
slices := [][]string{imports.Standard, imports.External, imports.Internal}
for sn, slice := range slices {
sort.Strings(slice)
for pn, path := range slice {
p(`"%s"`, path)
if pn == len(slice)-1 && sn < len(slices)-1 {
p("")
}
}
}
p(")")
p("")
result += fileBody
fmt.Printf("\n\n\nHERE:%v\n\n\n", result)
output, err := format.Source([]byte(result))
if err != nil {
return nil, err