Skip to content

Commit c0023b3

Browse files
authored
refactor(codegen): update code generation to use non-global root (#3721)
* refactor(codegen): update code generation to use non-global root expressions This commit modifies the code generation logic to consistently utilize a non-global root expressions across various files. Changes include updating function signatures and internal calls to pass the root expression, ensuring that the generated code correctly references the API structure. This refactor removes the need for code generation algorithms to refer to the global root expression variable. * refactor(codegen): improve ServicesData naming and structure consistency - Embed service.ServicesData in transport packages to eliminate confusing field names - Rename transport service maps to GRPCServices/HTTPServices for clarity - Add constructor functions to reduce boilerplate initialization - Update variable names from serviceData to services for semantic accuracy - Establish consistent patterns across service, HTTP, and gRPC codegen packages This eliminates the confusing naming where ServicesData contained a ServiceData field, and creates clear separation between service layer and transport layer data structures. * refactor(codegen): streamline service file generation and enhance template handling - Consolidate file appending in Service function for improved readability. - Simplify section template creation in EndpointFile and ViewsFile functions. - Introduce IsAliased and ServiceTypeRef fields in ServiceData for better type resolution. - Update request initialization template to utilize new fields for aliased types. These changes enhance the clarity and efficiency of the code generation process, ensuring better maintainability and consistency across service files.
1 parent 633f9fc commit c0023b3

88 files changed

Lines changed: 1043 additions & 1047 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

codegen/example/example_client.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func CLIFiles(genpkg string, root *expr.RootExpr) []*codegen.File {
2424
// exampleCLIMain returns an example client tool main implementation for the
2525
// given server expression.
2626
func exampleCLIMain(_ string, root *expr.RootExpr, svr *expr.ServerExpr) *codegen.File {
27-
svrdata := Servers.Get(svr)
27+
svrdata := Servers.Get(svr, root)
2828

2929
path := filepath.Join("cmd", svrdata.Dir+"-cli", "main.go")
3030
if _, err := os.Stat(path); !os.IsNotExist(err) {

codegen/example/example_client_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99

1010
"goa.design/goa/v3/codegen"
1111
"goa.design/goa/v3/codegen/example/testdata"
12-
"goa.design/goa/v3/expr"
1312
)
1413

1514
func TestExampleCLIFiles(t *testing.T) {
@@ -27,8 +26,8 @@ func TestExampleCLIFiles(t *testing.T) {
2726
t.Run(c.Name, func(t *testing.T) {
2827
// reset global variable
2928
Servers = make(ServersData)
30-
codegen.RunDSL(t, c.DSL)
31-
fs := CLIFiles("", expr.Root)
29+
root := codegen.RunDSL(t, c.DSL)
30+
fs := CLIFiles("", root)
3231
require.Len(t, fs, 1)
3332
require.Greater(t, len(fs[0].SectionTemplates), 0)
3433
var buf bytes.Buffer

codegen/example/example_server.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ import (
1313

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

2626
// exampleSvrMain returns the default main function for the given server
2727
// expression.
28-
func exampleSvrMain(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr) *codegen.File {
29-
svrdata := Servers.Get(svr)
28+
func exampleSvrMain(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr, services *service.ServicesData) *codegen.File {
29+
svrdata := Servers.Get(svr, root)
3030
mainPath := filepath.Join("cmd", svrdata.Dir, "main.go")
3131
if _, err := os.Stat(mainPath); !os.IsNotExist(err) {
3232
return nil // file already exists, skip it.
@@ -52,7 +52,7 @@ func exampleSvrMain(genpkg string, root *expr.RootExpr, svr *expr.ServerExpr) *c
5252
scope := codegen.NewNameScope()
5353
hasInterceptors := false
5454
for i, svc := range svr.Services {
55-
sd := service.Services.Get(svc)
55+
sd := services.Get(svc)
5656
svcData[i] = sd
5757
specs = append(specs, &codegen.ImportSpec{
5858
Path: path.Join(genpkg, sd.PathName),

codegen/example/example_server_test.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
"goa.design/goa/v3/codegen"
1515
"goa.design/goa/v3/codegen/example/testdata"
1616
"goa.design/goa/v3/codegen/service"
17-
"goa.design/goa/v3/expr"
1817
)
1918

2019
// updateGolden is true when -w is passed to `go test`, e.g. `go test ./... -w`
@@ -60,10 +59,10 @@ func TestExampleServerFiles(t *testing.T) {
6059
}
6160
for _, c := range cases {
6261
t.Run(c.Name, func(t *testing.T) {
63-
service.Services = make(service.ServicesData)
6462
Servers = make(ServersData)
65-
codegen.RunDSL(t, c.DSL)
66-
fs := ServerFiles("", expr.Root)
63+
root := codegen.RunDSL(t, c.DSL)
64+
services := service.NewServicesData(root)
65+
fs := ServerFiles("", root, services)
6766
require.Len(t, fs, 1)
6867
require.Greater(t, len(fs[0].SectionTemplates), 0)
6968
var buf bytes.Buffer

codegen/example/server_data.go

Lines changed: 83 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,11 @@ const (
109109

110110
// Get returns the server data for the given server expression. It builds the
111111
// server data if the server name does not exist in the map.
112-
func (d ServersData) Get(svr *expr.ServerExpr) *Data {
112+
func (d ServersData) Get(svr *expr.ServerExpr, root *expr.RootExpr) *Data {
113113
if data, ok := d[svr.Name]; ok {
114114
return data
115115
}
116-
sd := buildServerData(svr)
116+
sd := buildServerData(svr, root)
117117
d[svr.Name] = sd
118118
return sd
119119
}
@@ -170,31 +170,27 @@ func (h *HostData) DefaultURL(transport Transport) string {
170170
}
171171

172172
// buildServerData builds the server data for the given server expression.
173-
func buildServerData(svr *expr.ServerExpr) *Data {
173+
func buildServerData(svr *expr.ServerExpr, root *expr.RootExpr) *Data {
174174
var (
175175
hosts []*HostData
176176
)
177-
{
178-
for _, h := range svr.Hosts {
179-
hosts = append(hosts, buildHostData(h))
180-
}
177+
for _, h := range svr.Hosts {
178+
hosts = append(hosts, buildHostData(h))
181179
}
182180

183181
var (
184182
variables []*VariableData
185183

186184
foundVars = make(map[string]struct{})
187185
)
188-
{
189-
// collect all the URL variables defined in host expressions
190-
for _, h := range hosts {
191-
for _, v := range h.Variables {
192-
if _, ok := foundVars[v.Name]; ok {
193-
continue
194-
}
195-
variables = append(variables, v)
196-
foundVars[v.Name] = struct{}{}
186+
// collect all the URL variables defined in host expressions
187+
for _, h := range hosts {
188+
for _, v := range h.Variables {
189+
if _, ok := foundVars[v.Name]; ok {
190+
continue
197191
}
192+
variables = append(variables, v)
193+
foundVars[v.Name] = struct{}{}
198194
}
199195
}
200196

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

206202
foundTrans = make(map[Transport]struct{})
207203
)
208-
{
209-
for _, svc := range svr.Services {
210-
_, seenHTTP := foundTrans[TransportHTTP]
211-
_, seenGRPC := foundTrans[TransportGRPC]
212-
if expr.Root.API.HTTP.Service(svc) != nil {
213-
httpServices = append(httpServices, svc)
214-
if !seenHTTP {
215-
transports = append(transports, newHTTPTransport())
216-
foundTrans[TransportHTTP] = struct{}{}
217-
}
204+
for _, svc := range svr.Services {
205+
_, seenHTTP := foundTrans[TransportHTTP]
206+
_, seenGRPC := foundTrans[TransportGRPC]
207+
if root.API.HTTP.Service(svc) != nil {
208+
httpServices = append(httpServices, svc)
209+
if !seenHTTP {
210+
transports = append(transports, newHTTPTransport())
211+
foundTrans[TransportHTTP] = struct{}{}
218212
}
219-
if expr.Root.API.GRPC.Service(svc) != nil {
220-
grpcServices = append(grpcServices, svc)
221-
if !seenGRPC {
222-
transports = append(transports, newGRPCTransport())
223-
foundTrans[TransportGRPC] = struct{}{}
224-
}
213+
}
214+
if root.API.GRPC.Service(svc) != nil {
215+
grpcServices = append(grpcServices, svc)
216+
if !seenGRPC {
217+
transports = append(transports, newGRPCTransport())
218+
foundTrans[TransportGRPC] = struct{}{}
225219
}
226220
}
227221
}
@@ -247,79 +241,68 @@ func buildServerData(svr *expr.ServerExpr) *Data {
247241

248242
// buildHostData builds the host data for the given host expression.
249243
func buildHostData(host *expr.HostExpr) *HostData {
250-
var (
251-
uris []*URIData
252-
)
253-
{
254-
uris = make([]*URIData, len(host.URIs))
255-
for i, uv := range host.URIs {
256-
var (
257-
t *TransportData
258-
scheme string
259-
port string
244+
uris := make([]*URIData, len(host.URIs))
245+
for i, uv := range host.URIs {
246+
var (
247+
t *TransportData
248+
scheme string
249+
port string
260250

261-
ustr = string(uv)
262-
)
263-
{
264-
// Did not use url package to find scheme because the url may
265-
// contain params (i.e. http://{version}.example.com) which needs
266-
// substition for url.Parse to succeed. Also URIs in host must have
267-
// a scheme otherwise validations would have failed.
268-
switch {
269-
case strings.HasPrefix(ustr, "https"):
270-
scheme = "https"
271-
port = "443"
272-
t = newHTTPTransport()
273-
case strings.HasPrefix(ustr, "http"):
274-
scheme = "http"
275-
port = "80"
276-
t = newHTTPTransport()
277-
case strings.HasPrefix(ustr, "grpcs"):
278-
scheme = "grpcs"
279-
port = "8443"
280-
t = newGRPCTransport()
281-
case strings.HasPrefix(ustr, "grpc"):
282-
scheme = "grpc"
283-
port = "8080"
284-
t = newGRPCTransport()
251+
ustr = string(uv)
252+
)
253+
// Did not use url package to find scheme because the url may
254+
// contain params (i.e. http://{version}.example.com) which needs
255+
// substition for url.Parse to succeed. Also URIs in host must have
256+
// a scheme otherwise validations would have failed.
257+
switch {
258+
case strings.HasPrefix(ustr, "https"):
259+
scheme = "https"
260+
port = "443"
261+
t = newHTTPTransport()
262+
case strings.HasPrefix(ustr, "http"):
263+
scheme = "http"
264+
port = "80"
265+
t = newHTTPTransport()
266+
case strings.HasPrefix(ustr, "grpcs"):
267+
scheme = "grpcs"
268+
port = "8443"
269+
t = newGRPCTransport()
270+
case strings.HasPrefix(ustr, "grpc"):
271+
scheme = "grpc"
272+
port = "8080"
273+
t = newGRPCTransport()
285274

286-
// No need for default case here because we only support the above
287-
// possibilites for the scheme. Invalid scheme would have failed
288-
// validations in the first place.
289-
}
290-
}
291-
uris[i] = &URIData{
292-
Scheme: scheme,
293-
URL: ustr,
294-
Port: port,
295-
Transport: t,
296-
}
275+
// No need for default case here because we only support the above
276+
// possibilites for the scheme. Invalid scheme would have failed
277+
// validations in the first place.
278+
}
279+
uris[i] = &URIData{
280+
Scheme: scheme,
281+
URL: ustr,
282+
Port: port,
283+
Transport: t,
297284
}
298285
}
299286

300-
var (
301-
variables []*VariableData
302-
)
303-
{
304-
vars := expr.AsObject(host.Variables.Type)
305-
if len(*vars) > 0 {
306-
variables = make([]*VariableData, len(*vars))
307-
for i, v := range *vars {
308-
def := v.Attribute.DefaultValue
309-
var values []string
310-
if def == nil {
311-
def = v.Attribute.Validation.Values[0]
312-
// DSL ensures v.Attribute has either a
313-
// default value or an enum validation
314-
values = convertToString(v.Attribute.Validation.Values...)
315-
}
316-
variables[i] = &VariableData{
317-
Name: v.Name,
318-
Description: v.Attribute.Description,
319-
VarName: codegen.Goify(v.Name, false),
320-
DefaultValue: convertToString(def)[0],
321-
Values: values,
322-
}
287+
vars := expr.AsObject(host.Variables.Type)
288+
var variables []*VariableData
289+
if len(*vars) > 0 {
290+
variables = make([]*VariableData, len(*vars))
291+
for i, v := range *vars {
292+
def := v.Attribute.DefaultValue
293+
var values []string
294+
if def == nil {
295+
def = v.Attribute.Validation.Values[0]
296+
// DSL ensures v.Attribute has either a
297+
// default value or an enum validation
298+
values = convertToString(v.Attribute.Validation.Values...)
299+
}
300+
variables[i] = &VariableData{
301+
Name: v.Name,
302+
Description: v.Attribute.Description,
303+
VarName: codegen.Goify(v.Name, false),
304+
DefaultValue: convertToString(def)[0],
305+
Values: values,
323306
}
324307
}
325308
}

codegen/generator/example.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,21 @@ func Example(genpkg string, roots []eval.Root) ([]*codegen.File, error) {
2020
continue // could be a plugin root expression
2121
}
2222

23+
// Create service data
24+
services := service.NewServicesData(r)
25+
2326
// example service implementation
24-
if fs := service.ExampleServiceFiles(genpkg, r); len(fs) != 0 {
27+
if fs := service.ExampleServiceFiles(genpkg, r, services); len(fs) != 0 {
2528
files = append(files, fs...)
2629
}
2730

2831
// example interceptors implementation
29-
if fs := service.ExampleInterceptorsFiles(genpkg, r); len(fs) != 0 {
32+
if fs := service.ExampleInterceptorsFiles(genpkg, r, services); len(fs) != 0 {
3033
files = append(files, fs...)
3134
}
3235

3336
// server main
34-
if fs := example.ServerFiles(genpkg, r); len(fs) != 0 {
37+
if fs := example.ServerFiles(genpkg, r, services); len(fs) != 0 {
3538
files = append(files, fs...)
3639
}
3740

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

4346
// HTTP
4447
if len(r.API.HTTP.Services) > 0 {
45-
if fs := httpcodegen.ExampleServerFiles(genpkg, r); len(fs) != 0 {
48+
httpServices := httpcodegen.NewServicesData(services)
49+
if fs := httpcodegen.ExampleServerFiles(genpkg, httpServices); len(fs) != 0 {
4650
files = append(files, fs...)
4751
}
48-
if fs := httpcodegen.ExampleCLIFiles(genpkg, r); len(fs) != 0 {
52+
if fs := httpcodegen.ExampleCLIFiles(genpkg, httpServices); len(fs) != 0 {
4953
files = append(files, fs...)
5054
}
5155
}
5256

5357
// GRPC
5458
if len(r.API.GRPC.Services) > 0 {
55-
if fs := grpccodegen.ExampleServerFiles(genpkg, r); len(fs) > 0 {
59+
grpcServices := grpccodegen.NewServicesData(services)
60+
if fs := grpccodegen.ExampleServerFiles(genpkg, grpcServices); len(fs) > 0 {
5661
files = append(files, fs...)
5762
}
58-
if fs := grpccodegen.ExampleCLIFiles(genpkg, r); len(fs) > 0 {
63+
if fs := grpccodegen.ExampleCLIFiles(genpkg, grpcServices); len(fs) > 0 {
5964
files = append(files, fs...)
6065
}
6166
}
@@ -64,7 +69,7 @@ func Example(genpkg string, roots []eval.Root) ([]*codegen.File, error) {
6469
for _, f := range files {
6570
if len(f.SectionTemplates) > 0 {
6671
for _, s := range r.Services {
67-
service.AddServiceDataMetaTypeImports(f.SectionTemplates[0], s)
72+
service.AddServiceDataMetaTypeImports(f.SectionTemplates[0], s, services.Get(s.Name))
6873
}
6974
}
7075
}

0 commit comments

Comments
 (0)