Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion codegen/example/example_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func CLIFiles(genpkg string, root *expr.RootExpr) []*codegen.File {
// exampleCLIMain returns an example client tool main implementation for the
// given server expression.
func exampleCLIMain(_ string, root *expr.RootExpr, svr *expr.ServerExpr) *codegen.File {
svrdata := Servers.Get(svr)
svrdata := Servers.Get(svr, root)

path := filepath.Join("cmd", svrdata.Dir+"-cli", "main.go")
if _, err := os.Stat(path); !os.IsNotExist(err) {
Expand Down
5 changes: 2 additions & 3 deletions codegen/example/example_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

"goa.design/goa/v3/codegen"
"goa.design/goa/v3/codegen/example/testdata"
"goa.design/goa/v3/expr"
)

func TestExampleCLIFiles(t *testing.T) {
Expand All @@ -27,8 +26,8 @@ func TestExampleCLIFiles(t *testing.T) {
t.Run(c.Name, func(t *testing.T) {
// reset global variable
Servers = make(ServersData)
codegen.RunDSL(t, c.DSL)
fs := CLIFiles("", expr.Root)
root := codegen.RunDSL(t, c.DSL)
fs := CLIFiles("", root)
require.Len(t, fs, 1)
require.Greater(t, len(fs[0].SectionTemplates), 0)
var buf bytes.Buffer
Expand Down
10 changes: 5 additions & 5 deletions codegen/example/example_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import (

// ServerFiles returns an example server main implementation for every server
// expression in the service design.
func ServerFiles(genpkg string, root *expr.RootExpr) []*codegen.File {
func ServerFiles(genpkg string, root *expr.RootExpr, services *service.ServicesData) []*codegen.File {
var fw []*codegen.File
for _, svr := range root.API.Servers {
if m := exampleSvrMain(genpkg, root, svr); m != nil {
if m := exampleSvrMain(genpkg, root, svr, services); m != nil {
fw = append(fw, m)
}
}
Expand All @@ -25,8 +25,8 @@ func ServerFiles(genpkg string, root *expr.RootExpr) []*codegen.File {

// exampleSvrMain returns the default main function for the given server
// expression.
func exampleSvrMain(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr) *codegen.File {
svrdata := Servers.Get(svr)
func exampleSvrMain(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr, services *service.ServicesData) *codegen.File {
svrdata := Servers.Get(svr, root)
mainPath := filepath.Join("cmd", svrdata.Dir, "main.go")
if _, err := os.Stat(mainPath); !os.IsNotExist(err) {
return nil // file already exists, skip it.
Expand All @@ -52,7 +52,7 @@ func exampleSvrMain(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr) *c
scope := codegen.NewNameScope()
hasInterceptors := false
for i, svc := range svr.Services {
sd := service.Services.Get(svc)
sd := services.Get(svc)
svcData[i] = sd
specs = append(specs, &codegen.ImportSpec{
Path: path.Join(genpkg, sd.PathName),
Expand Down
7 changes: 3 additions & 4 deletions codegen/example/example_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"goa.design/goa/v3/codegen"
"goa.design/goa/v3/codegen/example/testdata"
"goa.design/goa/v3/codegen/service"
"goa.design/goa/v3/expr"
)

// updateGolden is true when -w is passed to `go test`, e.g. `go test ./... -w`
Expand Down Expand Up @@ -60,10 +59,10 @@ func TestExampleServerFiles(t *testing.T) {
}
for _, c := range cases {
t.Run(c.Name, func(t *testing.T) {
service.Services = make(service.ServicesData)
Servers = make(ServersData)
codegen.RunDSL(t, c.DSL)
fs := ServerFiles("", expr.Root)
root := codegen.RunDSL(t, c.DSL)
services := service.NewServicesData(root)
fs := ServerFiles("", root, services)
require.Len(t, fs, 1)
require.Greater(t, len(fs[0].SectionTemplates), 0)
var buf bytes.Buffer
Expand Down
183 changes: 83 additions & 100 deletions codegen/example/server_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,11 @@ const (

// Get returns the server data for the given server expression. It builds the
// server data if the server name does not exist in the map.
func (d ServersData) Get(svr *expr.ServerExpr) *Data {
func (d ServersData) Get(svr *expr.ServerExpr, root *expr.RootExpr) *Data {
if data, ok := d[svr.Name]; ok {
return data
}
sd := buildServerData(svr)
sd := buildServerData(svr, root)
d[svr.Name] = sd
return sd
}
Expand Down Expand Up @@ -170,31 +170,27 @@ func (h *HostData) DefaultURL(transport Transport) string {
}

// buildServerData builds the server data for the given server expression.
func buildServerData(svr *expr.ServerExpr) *Data {
func buildServerData(svr *expr.ServerExpr, root *expr.RootExpr) *Data {
var (
hosts []*HostData
)
{
for _, h := range svr.Hosts {
hosts = append(hosts, buildHostData(h))
}
for _, h := range svr.Hosts {
hosts = append(hosts, buildHostData(h))
}

var (
variables []*VariableData

foundVars = make(map[string]struct{})
)
{
// collect all the URL variables defined in host expressions
for _, h := range hosts {
for _, v := range h.Variables {
if _, ok := foundVars[v.Name]; ok {
continue
}
variables = append(variables, v)
foundVars[v.Name] = struct{}{}
// collect all the URL variables defined in host expressions
for _, h := range hosts {
for _, v := range h.Variables {
if _, ok := foundVars[v.Name]; ok {
continue
}
variables = append(variables, v)
foundVars[v.Name] = struct{}{}
}
}

Expand All @@ -205,23 +201,21 @@ func buildServerData(svr *expr.ServerExpr) *Data {

foundTrans = make(map[Transport]struct{})
)
{
for _, svc := range svr.Services {
_, seenHTTP := foundTrans[TransportHTTP]
_, seenGRPC := foundTrans[TransportGRPC]
if expr.Root.API.HTTP.Service(svc) != nil {
httpServices = append(httpServices, svc)
if !seenHTTP {
transports = append(transports, newHTTPTransport())
foundTrans[TransportHTTP] = struct{}{}
}
for _, svc := range svr.Services {
_, seenHTTP := foundTrans[TransportHTTP]
_, seenGRPC := foundTrans[TransportGRPC]
if root.API.HTTP.Service(svc) != nil {
httpServices = append(httpServices, svc)
if !seenHTTP {
transports = append(transports, newHTTPTransport())
foundTrans[TransportHTTP] = struct{}{}
}
if expr.Root.API.GRPC.Service(svc) != nil {
grpcServices = append(grpcServices, svc)
if !seenGRPC {
transports = append(transports, newGRPCTransport())
foundTrans[TransportGRPC] = struct{}{}
}
}
if root.API.GRPC.Service(svc) != nil {
grpcServices = append(grpcServices, svc)
if !seenGRPC {
transports = append(transports, newGRPCTransport())
foundTrans[TransportGRPC] = struct{}{}
}
}
}
Expand All @@ -247,79 +241,68 @@ func buildServerData(svr *expr.ServerExpr) *Data {

// buildHostData builds the host data for the given host expression.
func buildHostData(host *expr.HostExpr) *HostData {
var (
uris []*URIData
)
{
uris = make([]*URIData, len(host.URIs))
for i, uv := range host.URIs {
var (
t *TransportData
scheme string
port string
uris := make([]*URIData, len(host.URIs))
for i, uv := range host.URIs {
var (
t *TransportData
scheme string
port string

ustr = string(uv)
)
{
// Did not use url package to find scheme because the url may
// contain params (i.e. http://{version}.example.com) which needs
// substition for url.Parse to succeed. Also URIs in host must have
// a scheme otherwise validations would have failed.
switch {
case strings.HasPrefix(ustr, "https"):
scheme = "https"
port = "443"
t = newHTTPTransport()
case strings.HasPrefix(ustr, "http"):
scheme = "http"
port = "80"
t = newHTTPTransport()
case strings.HasPrefix(ustr, "grpcs"):
scheme = "grpcs"
port = "8443"
t = newGRPCTransport()
case strings.HasPrefix(ustr, "grpc"):
scheme = "grpc"
port = "8080"
t = newGRPCTransport()
ustr = string(uv)
)
// Did not use url package to find scheme because the url may
// contain params (i.e. http://{version}.example.com) which needs
// substition for url.Parse to succeed. Also URIs in host must have
// a scheme otherwise validations would have failed.
switch {
case strings.HasPrefix(ustr, "https"):
scheme = "https"
port = "443"
t = newHTTPTransport()
case strings.HasPrefix(ustr, "http"):
scheme = "http"
port = "80"
t = newHTTPTransport()
case strings.HasPrefix(ustr, "grpcs"):
scheme = "grpcs"
port = "8443"
t = newGRPCTransport()
case strings.HasPrefix(ustr, "grpc"):
scheme = "grpc"
port = "8080"
t = newGRPCTransport()

// No need for default case here because we only support the above
// possibilites for the scheme. Invalid scheme would have failed
// validations in the first place.
}
}
uris[i] = &URIData{
Scheme: scheme,
URL: ustr,
Port: port,
Transport: t,
}
// No need for default case here because we only support the above
// possibilites for the scheme. Invalid scheme would have failed
// validations in the first place.
}
uris[i] = &URIData{
Scheme: scheme,
URL: ustr,
Port: port,
Transport: t,
}
}

var (
variables []*VariableData
)
{
vars := expr.AsObject(host.Variables.Type)
if len(*vars) > 0 {
variables = make([]*VariableData, len(*vars))
for i, v := range *vars {
def := v.Attribute.DefaultValue
var values []string
if def == nil {
def = v.Attribute.Validation.Values[0]
// DSL ensures v.Attribute has either a
// default value or an enum validation
values = convertToString(v.Attribute.Validation.Values...)
}
variables[i] = &VariableData{
Name: v.Name,
Description: v.Attribute.Description,
VarName: codegen.Goify(v.Name, false),
DefaultValue: convertToString(def)[0],
Values: values,
}
vars := expr.AsObject(host.Variables.Type)
var variables []*VariableData
if len(*vars) > 0 {
variables = make([]*VariableData, len(*vars))
for i, v := range *vars {
def := v.Attribute.DefaultValue
var values []string
if def == nil {
def = v.Attribute.Validation.Values[0]
// DSL ensures v.Attribute has either a
// default value or an enum validation
values = convertToString(v.Attribute.Validation.Values...)
}
variables[i] = &VariableData{
Name: v.Name,
Description: v.Attribute.Description,
VarName: codegen.Goify(v.Name, false),
DefaultValue: convertToString(def)[0],
Values: values,
}
}
}
Expand Down
21 changes: 13 additions & 8 deletions codegen/generator/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,21 @@ func Example(genpkg string, roots []eval.Root) ([]*codegen.File, error) {
continue // could be a plugin root expression
}

// Create service data
services := service.NewServicesData(r)

// example service implementation
if fs := service.ExampleServiceFiles(genpkg, r); len(fs) != 0 {
if fs := service.ExampleServiceFiles(genpkg, r, services); len(fs) != 0 {
files = append(files, fs...)
}

// example interceptors implementation
if fs := service.ExampleInterceptorsFiles(genpkg, r); len(fs) != 0 {
if fs := service.ExampleInterceptorsFiles(genpkg, r, services); len(fs) != 0 {
files = append(files, fs...)
}

// server main
if fs := example.ServerFiles(genpkg, r); len(fs) != 0 {
if fs := example.ServerFiles(genpkg, r, services); len(fs) != 0 {
files = append(files, fs...)
}

Expand All @@ -42,20 +45,22 @@ func Example(genpkg string, roots []eval.Root) ([]*codegen.File, error) {

// HTTP
if len(r.API.HTTP.Services) > 0 {
if fs := httpcodegen.ExampleServerFiles(genpkg, r); len(fs) != 0 {
httpServices := httpcodegen.NewServicesData(services)
if fs := httpcodegen.ExampleServerFiles(genpkg, httpServices); len(fs) != 0 {
files = append(files, fs...)
}
if fs := httpcodegen.ExampleCLIFiles(genpkg, r); len(fs) != 0 {
if fs := httpcodegen.ExampleCLIFiles(genpkg, httpServices); len(fs) != 0 {
files = append(files, fs...)
}
}

// GRPC
if len(r.API.GRPC.Services) > 0 {
if fs := grpccodegen.ExampleServerFiles(genpkg, r); len(fs) > 0 {
grpcServices := grpccodegen.NewServicesData(services)
if fs := grpccodegen.ExampleServerFiles(genpkg, grpcServices); len(fs) > 0 {
files = append(files, fs...)
}
if fs := grpccodegen.ExampleCLIFiles(genpkg, r); len(fs) > 0 {
if fs := grpccodegen.ExampleCLIFiles(genpkg, grpcServices); len(fs) > 0 {
files = append(files, fs...)
}
}
Expand All @@ -64,7 +69,7 @@ func Example(genpkg string, roots []eval.Root) ([]*codegen.File, error) {
for _, f := range files {
if len(f.SectionTemplates) > 0 {
for _, s := range r.Services {
service.AddServiceDataMetaTypeImports(f.SectionTemplates[0], s)
service.AddServiceDataMetaTypeImports(f.SectionTemplates[0], s, services.Get(s.Name))
}
}
}
Expand Down
Loading