Repository: goadesign/goa (go)

Issue:
Invalid code generation when multiple APIs use different views of a result type 
I have an example created [here](https://github.com/SM43/user-goa/tree/view). Use the `view` branch of the repository.

I have 2 APIs defined in the [design](https://github.com/SM43/user-goa/blob/view/design/api.go). 
For both APIs, Result has the same ResultType `User` but with different views. 

API  `/user2` has `v1` view of `User`  &
API  `/user` has `default` view of `User`

When the code is generated, both are generated with the same view (v1).
This can be seen [here](https://github.com/SM43/user-goa/blob/072281b30e6094b90487ebeab9b208a2336d004b/gen/user/endpoints.go#L38). 

`NewGet2Endpoint` & `NewGetEndpoint` both have `NewViewedUser(res, "v1")`.

If the method [`get2`](https://github.com/SM43/user-goa/blob/072281b30e6094b90487ebeab9b208a2336d004b/design/api.go#L20) is moved after [`get`](https://github.com/SM43/user-goa/blob/072281b30e6094b90487ebeab9b208a2336d004b/design/api.go#L32). then the output is correct but the code generation is not.

The order of methods seems to be affecting the code generation. 

cc @raphael 

Pull request:
Handle multiple views for same result type
used in different methods when defined explcitely in method result.

Fix #2692

Patch:
diff --git a/codegen/service/service_data.go b/codegen/service/service_data.go
index 2035966f..6729307a 100644
--- a/codegen/service/service_data.go
+++ b/codegen/service/service_data.go
@@ -486,7 +486,6 @@ func (d ServicesData) analyze(service *expr.ServiceExpr) *Data {
 		seenErrors map[string]struct{}
 		seen       map[string]struct{}
 		seenProj   map[string]*ProjectedTypeData
-		seenViewed map[string]*ViewedResultTypeData
 	)
 	{
 		scope = codegen.NewNameScope()
@@ -497,7 +496,6 @@ func (d ServicesData) analyze(service *expr.ServiceExpr) *Data {
 		seen = make(map[string]struct{})
 		seenErrors = make(map[string]struct{})
 		seenProj = make(map[string]*ProjectedTypeData)
-		seenViewed = make(map[string]*ViewedResultTypeData)
 
 		// A function to collect user types from an error expression
 		recordError := func(er *expr.ErrorExpr) {
@@ -588,16 +586,11 @@ func (d ServicesData) analyze(service *expr.ServiceExpr) *Data {
 		for i, e := range service.Methods {
 			m := buildMethodData(e, pkgName, service, scope)
 			if rt, ok := e.Result.Type.(*expr.ResultTypeExpr); ok {
-				if vrt, ok := seenViewed[m.Result]; ok {
-					m.ViewedResult = vrt
-				} else {
-					projected := seenProj[rt.ID()]
-					projAtt := &expr.AttributeExpr{Type: projected.Type}
-					vrt := buildViewedResultType(e.Result, projAtt, viewspkg, scope, viewScope)
-					viewedRTs = append(viewedRTs, vrt)
-					seenViewed[vrt.Name] = vrt
-					m.ViewedResult = vrt
-				}
+				projected := seenProj[rt.ID()]
+				projAtt := &expr.AttributeExpr{Type: projected.Type}
+				vrt := buildViewedResultType(e.Result, projAtt, viewspkg, scope, viewScope)
+				viewedRTs = append(viewedRTs, vrt)
+				m.ViewedResult = vrt
 			}
 			methods[i] = m
 			for _, s := range m.Schemes {


Test patch:
diff --git a/codegen/service/testdata/endpoint_code.go b/codegen/service/testdata/endpoint_code.go
index cf10833f..d88acc6e 100644
--- a/codegen/service/testdata/endpoint_code.go
+++ b/codegen/service/testdata/endpoint_code.go
@@ -157,6 +157,7 @@ func NewAEndpoint(s Service) goa.Endpoint {
 const WithResultMultipleViewsEndpoint = `// Endpoints wraps the "WithResultMultipleViews" service endpoints.
 type Endpoints struct {
 	A goa.Endpoint
+	B goa.Endpoint
 }
 
 // NewEndpoints wraps the methods of the "WithResultMultipleViews" service with
@@ -164,6 +165,7 @@ type Endpoints struct {
 func NewEndpoints(s Service) *Endpoints {
 	return &Endpoints{
 		A: NewAEndpoint(s),
+		B: NewBEndpoint(s),
 	}
 }
 
@@ -171,17 +173,31 @@ func NewEndpoints(s Service) *Endpoints {
 // service endpoints.
 func (e *Endpoints) Use(m func(goa.Endpoint) goa.Endpoint) {
 	e.A = m(e.A)
+	e.B = m(e.B)
 }
 
 // NewAEndpoint returns an endpoint function that calls the method "A" of
 // service "WithResultMultipleViews".
 func NewAEndpoint(s Service) goa.Endpoint {
 	return func(ctx context.Context, req interface{}) (interface{}, error) {
-		res, view, err := s.A(ctx)
+		res, err := s.A(ctx)
+		if err != nil {
+			return nil, err
+		}
+		vres := NewViewedViewtype(res, "tiny")
+		return vres, nil
+	}
+}
+
+// NewBEndpoint returns an endpoint function that calls the method "B" of
+// service "WithResultMultipleViews".
+func NewBEndpoint(s Service) goa.Endpoint {
+	return func(ctx context.Context, req interface{}) (interface{}, error) {
+		res, err := s.B(ctx)
 		if err != nil {
 			return nil, err
 		}
-		vres := NewViewedViewtype(res, view)
+		vres := NewViewedViewtype(res, "default")
 		return vres, nil
 	}
 }
diff --git a/codegen/service/testdata/endpoint_dsls.go b/codegen/service/testdata/endpoint_dsls.go
index d6a11320..30a7d7d5 100644
--- a/codegen/service/testdata/endpoint_dsls.go
+++ b/codegen/service/testdata/endpoint_dsls.go
@@ -82,7 +82,14 @@ var WithResultMultipleViewsEndpointDSL = func() {
 	})
 	Service("WithResultMultipleViews", func() {
 		Method("A", func() {
-			Result(ViewType)
+			Result(ViewType, func() {
+				View("tiny")
+			})
+		})
+		Method("B", func() {
+			Result(ViewType, func() {
+				View("default")
+			})
 		})
 	})
 }