Repository: googleapis/gapic-generator-go
Pull request #1071 (2022-07-14 16:02:51)

fix(gengapic): fix unused imports
fixes: #1052


Patch:
diff --git a/internal/gengapic/genrest.go b/internal/gengapic/genrest.go
index 8c1147d..eec4784 100644
--- a/internal/gengapic/genrest.go
+++ b/internal/gengapic/genrest.go
@@ -97,9 +97,6 @@ func (g *generator) restClientInit(serv *descriptor.ServiceDescriptorProto, serv
 	g.restClientUtilities(serv, servName, imp, hasRPCForLRO)
 
 	g.imports[pbinfo.ImportSpec{Path: "net/http"}] = true
-	g.imports[pbinfo.ImportSpec{Path: "net/url"}] = true
-	g.imports[pbinfo.ImportSpec{Path: "io/ioutil"}] = true
-	g.imports[pbinfo.ImportSpec{Path: "fmt"}] = true
 	g.imports[pbinfo.ImportSpec{Path: "google.golang.org/grpc/metadata"}] = true
 	g.imports[pbinfo.ImportSpec{Name: "httptransport", Path: "google.golang.org/api/transport/http"}] = true
 	g.imports[pbinfo.ImportSpec{Path: "google.golang.org/api/option/internaloption"}] = true
@@ -395,6 +392,7 @@ func (g *generator) generateQueryString(m *descriptor.MethodDescriptorProto) {
 	}
 	sort.Strings(fields)
 
+	g.imports[pbinfo.ImportSpec{Path: "net/url"}] = true
 	p("params := url.Values{}")
 	for _, path := range fields {
 		field := queryParams[path]
@@ -403,6 +401,7 @@ func (g *generator) generateQueryString(m *descriptor.MethodDescriptorProto) {
 		singularPrimitive := field.GetType() != fieldTypeMessage &&
 			field.GetType() != fieldTypeBytes &&
 			field.GetLabel() != fieldLabelRepeated
+		g.imports[pbinfo.ImportSpec{Path: "fmt"}] = true
 		paramAdd := fmt.Sprintf("params.Add(%q, fmt.Sprintf(%q, req%s))", lowerFirst(snakeToCamel(path)), "%v", accessor)
 
 		// Only required, singular, primitive field types should be added regardless.
@@ -452,6 +451,7 @@ func (g *generator) generateBaseURL(info *httpInfo, ret string) {
 	// e.g. v1beta1/repeat/{info.f_string=first/*}/{info.f_child.f_string=second/**}:pathtrailingresource
 	fmtStr = httpPatternVarRegex.ReplaceAllStringFunc(fmtStr, func(s string) string { return "%v" })
 
+	g.imports[pbinfo.ImportSpec{Path: "net/url"}] = true
 	p("baseUrl, err := url.Parse(c.endpoint)")
 	p("if err != nil {")
 	p("  %s", ret)
@@ -465,6 +465,7 @@ func (g *generator) generateBaseURL(info *httpInfo, ret string) {
 		// See the docs for FindStringSubmatch for further details.
 		tokens = append(tokens, fmt.Sprintf("req%s", fieldGetter(path[1])))
 	}
+	g.imports[pbinfo.ImportSpec{Path: "fmt"}] = true
 	p("baseUrl.Path += fmt.Sprintf(%s)", strings.Join(tokens, ", "))
 	p("")
 }
@@ -711,6 +712,9 @@ func (g *generator) noRequestStreamRESTCall(servName string, s *descriptor.Servi
 	p("}")
 	p("")
 
+	g.imports[pbinfo.ImportSpec{Path: "context"}] = true
+	g.imports[pbinfo.ImportSpec{Path: "fmt"}] = true
+
 	return nil
 }
 
@@ -826,6 +830,7 @@ func (g *generator) pagingRESTCall(servName string, m *descriptor.MethodDescript
 	p("}")
 
 	g.imports[pbinfo.ImportSpec{Path: "google.golang.org/api/iterator"}] = true
+	g.imports[pbinfo.ImportSpec{Path: "io/ioutil"}] = true
 	g.imports[pbinfo.ImportSpec{Path: "google.golang.org/protobuf/proto"}] = true
 	g.imports[pbinfo.ImportSpec{Path: "google.golang.org/protobuf/encoding/protojson"}] = true
 	g.imports[pbinfo.ImportSpec{Path: "google.golang.org/api/googleapi"}] = true
@@ -941,6 +946,8 @@ func (g *generator) lroRESTCall(servName string, m *descriptor.MethodDescriptorP
 	p("}")
 	p("")
 
+	g.imports[pbinfo.ImportSpec{Path: "fmt"}] = true
+	g.imports[pbinfo.ImportSpec{Path: "io/ioutil"}] = true
 	g.imports[pbinfo.ImportSpec{Path: "cloud.google.com/go/longrunning"}] = true
 	g.imports[pbinfo.ImportSpec{Path: "google.golang.org/api/googleapi"}] = true
 	g.imports[pbinfo.ImportSpec{Path: "google.golang.org/grpc/metadata"}] = true
@@ -1150,6 +1157,7 @@ func (g *generator) unaryRESTCall(servName string, m *descriptor.MethodDescripto
 	p(ret)
 	p("}")
 
+	g.imports[pbinfo.ImportSpec{Path: "io/ioutil"}] = true
 	g.imports[pbinfo.ImportSpec{Path: "google.golang.org/api/googleapi"}] = true
 	g.imports[pbinfo.ImportSpec{Path: "google.golang.org/protobuf/encoding/protojson"}] = true
 	g.imports[inSpec] = true


Test patch:
diff --git a/internal/gengapic/client_init_test.go b/internal/gengapic/client_init_test.go
index 14fb769..13e1776 100644
--- a/internal/gengapic/client_init_test.go
+++ b/internal/gengapic/client_init_test.go
@@ -416,15 +416,12 @@ func TestClientInit(t *testing.T) {
 			serv:      servPlain,
 			parameter: proto.String("go-gapic-package=path;mypackage,transport=rest"),
 			imports: map[pbinfo.ImportSpec]bool{
-				{Path: "context"}:                      true,
-				{Path: "fmt"}:                          true,
-				{Path: "google.golang.org/api/option"}: true,
-				{Path: "google.golang.org/api/option/internaloption"}: true,
-				{Path: "google.golang.org/grpc"}:                      true,
-				{Path: "google.golang.org/grpc/metadata"}:             true,
-				{Path: "io/ioutil"}:                                   true,
-				{Path: "net/http"}:                                    true,
-				{Path: "net/url"}:                                     true,
+				{Path: "context"}:                                                     true,
+				{Path: "google.golang.org/api/option"}:                                true,
+				{Path: "google.golang.org/api/option/internaloption"}:                 true,
+				{Path: "google.golang.org/grpc"}:                                      true,
+				{Path: "google.golang.org/grpc/metadata"}:                             true,
+				{Path: "net/http"}:                                                    true,
 				{Name: "httptransport", Path: "google.golang.org/api/transport/http"}: true,
 			},
 		},
@@ -434,15 +431,12 @@ func TestClientInit(t *testing.T) {
 			serv:      servPlain,
 			parameter: proto.String("go-gapic-package=path;mypackage,transport=grpc+rest"),
 			imports: map[pbinfo.ImportSpec]bool{
-				{Path: "fmt"}:                                         true,
-				{Path: "google.golang.org/api/option"}:                true,
-				{Path: "google.golang.org/api/option/internaloption"}: true,
-				{Path: "io/ioutil"}:                                   true,
-				{Path: "net/http"}:                                    true,
-				{Path: "net/url"}:                                     true,
-				{Path: "context"}:                                     true,
-				{Path: "google.golang.org/grpc"}:                      true,
-				{Path: "google.golang.org/grpc/metadata"}:             true,
+				{Path: "google.golang.org/api/option"}:                                true,
+				{Path: "google.golang.org/api/option/internaloption"}:                 true,
+				{Path: "net/http"}:                                                    true,
+				{Path: "context"}:                                                     true,
+				{Path: "google.golang.org/grpc"}:                                      true,
+				{Path: "google.golang.org/grpc/metadata"}:                             true,
 				{Name: "gtransport", Path: "google.golang.org/api/transport/grpc"}:    true,
 				{Name: "mypackagepb", Path: "github.com/googleapis/mypackage"}:        true,
 				{Name: "httptransport", Path: "google.golang.org/api/transport/http"}: true,
@@ -476,15 +470,12 @@ func TestClientInit(t *testing.T) {
 				{Name: "gtransport", Path: "google.golang.org/api/transport/grpc"}:    true,
 				{Name: "httptransport", Path: "google.golang.org/api/transport/http"}: true,
 				{Name: "mypackagepb", Path: "github.com/googleapis/mypackage"}:        true,
-				{Path: "context"}:                      true,
-				{Path: "fmt"}:                          true,
-				{Path: "google.golang.org/api/option"}: true,
+				{Path: "context"}:                                     true,
+				{Path: "google.golang.org/api/option"}:                true,
 				{Path: "google.golang.org/api/option/internaloption"}: true,
 				{Path: "google.golang.org/grpc"}:                      true,
 				{Path: "google.golang.org/grpc/metadata"}:             true,
-				{Path: "io/ioutil"}:                                   true,
 				{Path: "net/http"}:                                    true,
-				{Path: "net/url"}:                                     true,
 			},
 		},
 		{
@@ -494,15 +485,12 @@ func TestClientInit(t *testing.T) {
 			customOpServ: opS,
 			parameter:    proto.String("go-gapic-package=path;mypackage,transport=rest,diregapic"),
 			imports: map[pbinfo.ImportSpec]bool{
-				{Path: "context"}:                      true,
-				{Path: "fmt"}:                          true,
-				{Path: "google.golang.org/api/option"}: true,
-				{Path: "google.golang.org/api/option/internaloption"}: true,
-				{Path: "google.golang.org/grpc"}:                      true,
-				{Path: "google.golang.org/grpc/metadata"}:             true,
-				{Path: "io/ioutil"}:                                   true,
-				{Path: "net/http"}:                                    true,
-				{Path: "net/url"}:                                     true,
+				{Path: "context"}:                                                     true,
+				{Path: "google.golang.org/api/option"}:                                true,
+				{Path: "google.golang.org/api/option/internaloption"}:                 true,
+				{Path: "google.golang.org/grpc"}:                                      true,
+				{Path: "google.golang.org/grpc/metadata"}:                             true,
+				{Path: "net/http"}:                                                    true,
 				{Name: "httptransport", Path: "google.golang.org/api/transport/http"}: true,
 			},
 		},
diff --git a/internal/gengapic/genrest_test.go b/internal/gengapic/genrest_test.go
index 2adcf79..8c4b556 100644
--- a/internal/gengapic/genrest_test.go
+++ b/internal/gengapic/genrest_test.go
@@ -551,6 +551,15 @@ func TestGenRestMethod(t *testing.T) {
 		Options: unaryRPCOpt,
 	}
 
+	clientStreamRPC := &descriptor.MethodDescriptorProto{
+		Name:            proto.String("ClientStreamRPC"),
+		InputType:       proto.String(foofqn),
+		OutputType:      proto.String(foofqn),
+		ClientStreaming: proto.Bool(true),
+		// Reuse the unary RPC options because it's basically the same.
+		Options: unaryRPCOpt,
+	}
+
 	lroRPCOpt := &descriptor.MethodOptions{}
 	proto.SetExtension(lroRPCOpt, annotations.E_Http, &annotations.HttpRule{
 		Pattern: &annotations.HttpRule_Post{
@@ -637,6 +646,7 @@ func TestGenRestMethod(t *testing.T) {
 				unaryRPC:        s,
 				pagingRPC:       s,
 				serverStreamRPC: s,
+				clientStreamRPC: s,
 				lroRPC:          s,
 				httpBodyRPC:     s,
 				nameField:       op,
@@ -666,7 +676,10 @@ func TestGenRestMethod(t *testing.T) {
 			method:  opRPC,
 			options: &options{diregapic: true},
 			imports: map[pbinfo.ImportSpec]bool{
-				{Path: "google.golang.org/protobuf/encoding/protojson"}:          true,
+				{Path: "google.golang.org/protobuf/encoding/protojson"}: true,
+				{Path: "io/ioutil"}: true,
+				{Path: "net/url"}:   true,
+				{Path: "fmt"}:       true,
 				{Path: "google.golang.org/api/googleapi"}:                        true,
 				{Name: "foopb", Path: "google.golang.org/genproto/cloud/foo/v1"}: true,
 			},
@@ -690,10 +703,11 @@ func TestGenRestMethod(t *testing.T) {
 				{Path: "bytes"}: true,
 				{Path: "fmt"}:   true,
 				{Path: "google.golang.org/protobuf/encoding/protojson"}: true,
-				{Path: "google.golang.org/api/googleapi"}:               true,
-				{Path: "net/url"}: true,
-				{Path: "regexp"}:  true,
-				{Path: "strings"}: true,
+				{Path: "io/ioutil"}:                       true,
+				{Path: "google.golang.org/api/googleapi"}: true,
+				{Path: "net/url"}:                         true,
+				{Path: "regexp"}:                          true,
+				{Path: "strings"}:                         true,
 				{Name: "foopb", Path: "google.golang.org/genproto/cloud/foo/v1"}: true,
 			},
 		},
@@ -702,11 +716,14 @@ func TestGenRestMethod(t *testing.T) {
 			method:  pagingRPC,
 			options: &options{},
 			imports: map[pbinfo.ImportSpec]bool{
-				{Path: "math"}: true,
-				{Path: "google.golang.org/protobuf/encoding/protojson"}:          true,
+				{Path: "math"}:    true,
+				{Path: "net/url"}: true,
+				{Path: "google.golang.org/protobuf/encoding/protojson"}: true,
+				{Path: "fmt"}: true,
 				{Path: "google.golang.org/api/googleapi"}:                        true,
 				{Path: "google.golang.org/api/iterator"}:                         true,
 				{Path: "google.golang.org/protobuf/proto"}:                       true,
+				{Path: "io/ioutil"}:                                              true,
 				{Name: "foopb", Path: "google.golang.org/genproto/cloud/foo/v1"}: true,
 			},
 		},
@@ -727,18 +744,31 @@ func TestGenRestMethod(t *testing.T) {
 				{Name: "foopb", Path: "google.golang.org/genproto/cloud/foo/v1"}: true,
 			},
 		},
+		{
+			name:    "no_request_stream_rpc",
+			method:  clientStreamRPC,
+			options: &options{},
+			imports: map[pbinfo.ImportSpec]bool{
+				{Path: "context"}: true,
+				{Path: "fmt"}:     true,
+				{Name: "foopb", Path: "google.golang.org/genproto/cloud/foo/v1"}: true,
+			},
+		},
 		{
 			name:    "lro_rpc",
 			method:  lroRPC,
 			options: &options{transports: []transport{rest}},
 			imports: map[pbinfo.ImportSpec]bool{
 				{Path: "bytes"}: true,
-				{Path: "cloud.google.com/go/longrunning"}:               true,
-				{Path: "google.golang.org/api/googleapi"}:               true,
-				{Path: "google.golang.org/grpc/metadata"}:               true,
-				{Path: "google.golang.org/protobuf/encoding/protojson"}: true,
-				{Path: "time"}: true,
-				{Name: "foopb", Path: "google.golang.org/genproto/cloud/foo/v1"}:                   true,
+				{Path: "cloud.google.com/go/longrunning"}: true,
+				{Path: "fmt"}: true,
+				{Path: "google.golang.org/api/googleapi"}:                        true,
+				{Path: "google.golang.org/grpc/metadata"}:                        true,
+				{Path: "google.golang.org/protobuf/encoding/protojson"}:          true,
+				{Path: "io/ioutil"}:                                              true,
+				{Path: "net/url"}:                                                true,
+				{Path: "time"}:                                                   true,
+				{Name: "foopb", Path: "google.golang.org/genproto/cloud/foo/v1"}: true,
 				{Name: "longrunningpb", Path: "google.golang.org/genproto/googleapis/longrunning"}: true,
 			},
 		},
@@ -750,10 +780,11 @@ func TestGenRestMethod(t *testing.T) {
 				{Path: "bytes"}: true,
 				{Path: "fmt"}:   true,
 				{Path: "google.golang.org/protobuf/encoding/protojson"}: true,
-				{Path: "google.golang.org/api/googleapi"}:               true,
-				{Path: "net/url"}: true,
-				{Path: "regexp"}:  true,
-				{Path: "strings"}: true,
+				{Path: "io/ioutil"}:                       true,
+				{Path: "google.golang.org/api/googleapi"}: true,
+				{Path: "net/url"}:                         true,
+				{Path: "regexp"}:                          true,
+				{Path: "strings"}:                         true,
 				{Name: "foopb", Path: "google.golang.org/genproto/cloud/foo/v1"}:                 true,
 				{Name: "httpbodypb", Path: "google.golang.org/genproto/googleapis/api/httpbody"}: true,
 			},
diff --git a/internal/gengapic/testdata/rest_ClientStreamRPC.want b/internal/gengapic/testdata/rest_ClientStreamRPC.want
new file mode 100644
index 0000000..28b66b4
--- /dev/null
+++ b/internal/gengapic/testdata/rest_ClientStreamRPC.want
@@ -0,0 +1,4 @@
+func (c *fooRESTClient) ClientStreamRPC(ctx context.Context, opts ...gax.CallOption) (foopb.FooService_ClientStreamRPCClient, error) {
+	return nil, fmt.Errorf("ClientStreamRPC not yet supported for REST clients")
+}
+