analyze creates the data necessary to render the code of the given service. It records the user types needed by the service definition in userTypes.
(service *expr.ServiceExpr)
| 735 | // analyze creates the data necessary to render the code of the given service. |
| 736 | // It records the user types needed by the service definition in userTypes. |
| 737 | func (d *ServicesData) analyze(service *expr.ServiceExpr) *Data { |
| 738 | var ( |
| 739 | types []*UserTypeData |
| 740 | errTypes []*UserTypeData |
| 741 | errorInits []*ErrorInitData |
| 742 | projTypes []*ProjectedTypeData |
| 743 | viewedRTs []*ViewedResultTypeData |
| 744 | ) |
| 745 | scope := codegen.NewNameScope() |
| 746 | scope.Unique("Use") // Reserve "Use" for Endpoints struct Use method. |
| 747 | scope.Unique("websocket") // Reserve "websocket" to avoid collision with gorilla/websocket |
| 748 | viewScope := codegen.NewNameScope() |
| 749 | pkgName := scope.HashedUnique(service, strings.ToLower(codegen.Goify(service.Name, false)), "svc") |
| 750 | viewspkg := pkgName + "views" |
| 751 | seen := make(map[string]struct{}) |
| 752 | seenErrors := make(map[string]struct{}) |
| 753 | seenProj := make(map[string]*ProjectedTypeData) |
| 754 | seenViewed := make(map[string]*ViewedResultTypeData) |
| 755 | |
| 756 | // A function to collect user types from an error expression |
| 757 | recordError := func(er *expr.ErrorExpr) { |
| 758 | errTypes = append(errTypes, collectTypes(er.AttributeExpr, scope, seen, nil)...) |
| 759 | if er.Type == expr.ErrorResult { |
| 760 | if _, ok := seenErrors[er.Name]; ok { |
| 761 | return |
| 762 | } |
| 763 | seenErrors[er.Name] = struct{}{} |
| 764 | errorInits = append(errorInits, buildErrorInitData(er, scope)) |
| 765 | } |
| 766 | } |
| 767 | for _, er := range service.Errors { |
| 768 | recordError(er) |
| 769 | } |
| 770 | |
| 771 | // A function to collect inner user types from an attribute expression |
| 772 | collectUserTypes := func(att *expr.AttributeExpr) { |
| 773 | if att == nil { |
| 774 | return |
| 775 | } |
| 776 | var loc *codegen.Location |
| 777 | if ut, ok := att.Type.(expr.UserType); ok { |
| 778 | loc = codegen.UserTypeLocation(ut) |
| 779 | att = ut.Attribute() |
| 780 | } |
| 781 | types = append(types, collectTypes(att, scope, seen, loc)...) |
| 782 | } |
| 783 | for _, m := range service.Methods { |
| 784 | // collect inner user types |
| 785 | collectUserTypes(m.Payload) |
| 786 | collectUserTypes(m.StreamingPayload) |
| 787 | collectUserTypes(m.Result) |
| 788 | // Collect streaming result types if different from Result |
| 789 | if m.HasMixedResults() { |
| 790 | collectUserTypes(m.StreamingResult) |
| 791 | } |
| 792 | // Collect projected types |
| 793 | if hasResultType(m.Result) { |
| 794 | ptypes := collectProjectedTypes(expr.DupAtt(m.Result), m.Result, viewspkg, scope, viewScope, seenProj) |
no test coverage detected