ViewsFile returns the views file for the given service which contains logic to render result types using the defined views.
(_ string, service *expr.ServiceExpr, services *ServicesData)
| 18 | // ViewsFile returns the views file for the given service which contains |
| 19 | // logic to render result types using the defined views. |
| 20 | func ViewsFile(_ string, service *expr.ServiceExpr, services *ServicesData) *codegen.File { |
| 21 | svc := services.Get(service.Name) |
| 22 | if len(svc.projectedTypes) == 0 { |
| 23 | return nil |
| 24 | } |
| 25 | |
| 26 | // Collect union sum-type definitions for the views package. |
| 27 | // |
| 28 | // View-projected types cannot import the service package (which already |
| 29 | // depends on views), therefore unions must be generated in the views package |
| 30 | // when referenced by projected types. |
| 31 | unionByHash := make(map[string]*UnionTypeData) |
| 32 | seenUnions := make(map[string]struct{}) |
| 33 | viewLoc := &codegen.Location{RelImportPath: "views"} |
| 34 | for _, t := range svc.projectedTypes { |
| 35 | collectViewUnionTypes(&expr.AttributeExpr{Type: t.Type}, svc.ViewScope, viewLoc, unionByHash, seenUnions) |
| 36 | } |
| 37 | unions := make([]*UnionTypeData, 0, len(unionByHash)) |
| 38 | for _, u := range unionByHash { |
| 39 | unions = append(unions, u) |
| 40 | } |
| 41 | sort.Slice(unions, func(i, j int) bool { |
| 42 | return unions[i].Name < unions[j].Name |
| 43 | }) |
| 44 | |
| 45 | path := filepath.Join(codegen.Gendir, svc.PathName, "views", "view.go") |
| 46 | imports := []*codegen.ImportSpec{ |
| 47 | codegen.GoaImport(""), |
| 48 | {Path: "unicode/utf8"}, |
| 49 | } |
| 50 | if len(unions) > 0 { |
| 51 | imports = append(imports, |
| 52 | codegen.SimpleImport("encoding/json"), |
| 53 | codegen.SimpleImport("fmt"), |
| 54 | ) |
| 55 | } |
| 56 | header := codegen.Header(service.Name+" views", "views", |
| 57 | imports) |
| 58 | sections := []*codegen.SectionTemplate{header} |
| 59 | |
| 60 | // type definitions |
| 61 | for _, t := range svc.viewedResultTypes { |
| 62 | sections = append(sections, &codegen.SectionTemplate{ |
| 63 | Name: "viewed-result-type", |
| 64 | Source: serviceTemplates.Read(userTypeT), |
| 65 | Data: t.UserTypeData, |
| 66 | }) |
| 67 | } |
| 68 | for _, t := range svc.projectedTypes { |
| 69 | sections = append(sections, &codegen.SectionTemplate{ |
| 70 | Name: "projected-type", |
| 71 | Source: serviceTemplates.Read(userTypeT), |
| 72 | Data: t.UserTypeData, |
| 73 | }) |
| 74 | } |
| 75 | for _, u := range unions { |
| 76 | sections = append(sections, &codegen.SectionTemplate{ |
| 77 | Name: "projected-union-type", |