From b72d9b7f031ada43705d2116119768eb0c276364 Mon Sep 17 00:00:00 2001 From: Julie Qiu Date: Thu, 28 Nov 2024 22:01:58 -0500 Subject: [PATCH 1/2] impl(internal/api): create package Move the internal API and LanguageCode models to a separate package. --- generator/internal/api/codec.go | 117 +++++++ .../internal/{genclient => api}/model.go | 2 +- generator/internal/genclient/genclient.go | 107 +----- generator/internal/genclient/templatedata.go | 75 ++--- generator/internal/language/api_test.go | 14 +- generator/internal/language/golang.go | 59 ++-- generator/internal/language/golang_test.go | 58 ++-- generator/internal/language/rust.go | 155 ++++----- generator/internal/language/rust_test.go | 267 +++++++-------- generator/internal/parser/annotations.go | 22 +- generator/internal/parser/mixin.go | 4 +- generator/internal/parser/openapi.go | 190 +++++------ generator/internal/parser/openapi_test.go | 240 +++++++------- generator/internal/parser/protobuf.go | 121 +++---- generator/internal/parser/protobuf_test.go | 306 +++++++++--------- generator/internal/sidekick/refresh.go | 13 +- 16 files changed, 882 insertions(+), 868 deletions(-) create mode 100644 generator/internal/api/codec.go rename generator/internal/{genclient => api}/model.go (99%) diff --git a/generator/internal/api/codec.go b/generator/internal/api/codec.go new file mode 100644 index 000000000..c9fad8705 --- /dev/null +++ b/generator/internal/api/codec.go @@ -0,0 +1,117 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package api + +// LanguageCodec is an adapter used to transform values into language idiomatic +// representations. This is used to manipulate the data the is fed into +// templates to generate clients. +type LanguageCodec interface { + // TemplateDir returns the directory containing the templates. + TemplateDir() string + // LoadWellKnownTypes allows a language to load information into the state + // for any wellknown types. For example defining how timestamppb should be + // represented in a given language or wrappers around operations. + LoadWellKnownTypes(s *APIState) + // FieldAttributes returns a (possibly empty) list of "attributes" included + // immediately before the field definition. + FieldAttributes(f *Field, state *APIState) []string + // FieldType returns a string representation of a message field type. + FieldType(f *Field, state *APIState) string + // The field when used to build the query. + AsQueryParameter(f *Field, state *APIState) string + // The name of a message type ID when used as an input or output argument + // in the client methods. + MethodInOutTypeName(id string, state *APIState) string + // Returns a (possibly empty) list of "attributes" included immediately + // before the message definition. + MessageAttributes(m *Message, state *APIState) []string + // The (unqualified) message name, as used when defining the type to + // represent it. + MessageName(m *Message, state *APIState) string + // The fully-qualified message name, as used when referring to the name from + // another place in the package. + FQMessageName(m *Message, state *APIState) string + // The (unqualified) enum name, as used when defining the type to + // represent it. + EnumName(e *Enum, state *APIState) string + // The fully-qualified enum name, as used when referring to the name from + // another place in the package. + FQEnumName(e *Enum, state *APIState) string + // The (unqualified) enum value name, as used when defining the constant, + // variable, or enum value that holds it. + EnumValueName(e *EnumValue, state *APIState) string + // The fully qualified enum value name, as used when using the constant, + // variable, or enum value that holds it. + FQEnumValueName(e *EnumValue, state *APIState) string + // OneOfType returns a string representation of a one-of field type. + OneOfType(o *OneOf, state *APIState) string + // BodyAccessor returns a string representation of the accessor used to + // get the body out of a request. For instance this might return `.Body()`. + BodyAccessor(m *Method, state *APIState) string + // HTTPPathFmt returns a format string used for adding path arguments to a + // URL. The replacements should align in both order and value from what is + // returned from HTTPPathArgs. + HTTPPathFmt(m *PathInfo, state *APIState) string + // HTTPPathArgs returns a string representation of the path arguments. This + // should be used in conjunction with HTTPPathFmt. An example return value + // might be `, req.PathParam()` + HTTPPathArgs(h *PathInfo, state *APIState) []string + // QueryParams returns key-value pairs of name to accessor for query params. + // An example return value might be + // `&Pair{Key: "secretId", Value: "req.SecretId()"}` + QueryParams(m *Method, state *APIState) []*Field + // ToSnake converts a symbol name to `snake_case`, applying any mangling + // required by the language, e.g., to avoid clashes with reserved words. + ToSnake(string) string + // ToSnakeNoMangling converts a symbol name to `snake_case`, without any + // mangling to avoid reserved words. This is useful when the template is + // already going to mangle the name, e.g., by adding a prefix or suffix. + // Since the templates are language specific, their authors can determine + // when to use `ToSnake` or `ToSnakeNoMangling`. + ToSnakeNoMangling(string) string + // ToPascal converts a symbol name to `PascalCase`, applying any mangling + // required by the language, e.g., to avoid clashes with reserved words. + ToPascal(string) string + // ToCamel converts a symbol name to `camelCase` (sometimes called + // "lowercase CamelCase"), applying any mangling required by the language, + // e.g., to avoid clashes with reserved words. + ToCamel(string) string + // Reformat ${Lang}Doc comments according to the language-specific rules. + // For example, + // - The protos in googleapis include cross-references in the format + // `[Foo][proto.package.name.Foo]`, this should become links to the + // language entities, in the language documentation. + // - Rust requires a `norust` annotation in all blockquotes, that is, + // any ```-sections. Without this annotation Rustdoc assumes the + // blockquote is an Rust code snippet and attempts to compile it. + FormatDocComments(string) []string + // Returns a extra set of lines to insert in the module file. + // The format of these lines is specific to each language. + RequiredPackages() []string + // The package name in the destination language. May be empty, some + // languages do not have a package manager. + PackageName(api *API) string + // Validate an API, some codecs impose restrictions on the input API. + Validate(api *API) error + // The year when this package was first generated. + CopyrightYear() string + // Pass language-specific information from the Codec to the template engine. + // Prefer using specific methods when the information is applicable to most + // (or many) languages. Use this method when the information is application + // to only one language. + AdditionalContext() any + // Imports to add. + Imports() []string +} diff --git a/generator/internal/genclient/model.go b/generator/internal/api/model.go similarity index 99% rename from generator/internal/genclient/model.go rename to generator/internal/api/model.go index dfcabf94e..0c0feb87f 100644 --- a/generator/internal/genclient/model.go +++ b/generator/internal/api/model.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package genclient +package api import ( "regexp" diff --git a/generator/internal/genclient/genclient.go b/generator/internal/genclient/genclient.go index e4c1b69bb..72b4c185f 100644 --- a/generator/internal/genclient/genclient.go +++ b/generator/internal/genclient/genclient.go @@ -24,110 +24,9 @@ import ( "strings" "github.com/cbroglie/mustache" + "github.com/googleapis/google-cloud-rust/generator/internal/api" ) -// LanguageCodec is an adapter used to transform values into language idiomatic -// representations. This is used to manipulate the data the is fed into -// templates to generate clients. -type LanguageCodec interface { - // TemplateDir returns the directory containing the templates. - TemplateDir() string - // LoadWellKnownTypes allows a language to load information into the state - // for any wellknown types. For example defining how timestamppb should be - // represented in a given language or wrappers around operations. - LoadWellKnownTypes(s *APIState) - // FieldAttributes returns a (possibly empty) list of "attributes" included - // immediately before the field definition. - FieldAttributes(f *Field, state *APIState) []string - // FieldType returns a string representation of a message field type. - FieldType(f *Field, state *APIState) string - // The field when used to build the query. - AsQueryParameter(f *Field, state *APIState) string - // The name of a message type ID when used as an input or output argument - // in the client methods. - MethodInOutTypeName(id string, state *APIState) string - // Returns a (possibly empty) list of "attributes" included immediately - // before the message definition. - MessageAttributes(m *Message, state *APIState) []string - // The (unqualified) message name, as used when defining the type to - // represent it. - MessageName(m *Message, state *APIState) string - // The fully-qualified message name, as used when referring to the name from - // another place in the package. - FQMessageName(m *Message, state *APIState) string - // The (unqualified) enum name, as used when defining the type to - // represent it. - EnumName(e *Enum, state *APIState) string - // The fully-qualified enum name, as used when referring to the name from - // another place in the package. - FQEnumName(e *Enum, state *APIState) string - // The (unqualified) enum value name, as used when defining the constant, - // variable, or enum value that holds it. - EnumValueName(e *EnumValue, state *APIState) string - // The fully qualified enum value name, as used when using the constant, - // variable, or enum value that holds it. - FQEnumValueName(e *EnumValue, state *APIState) string - // OneOfType returns a string representation of a one-of field type. - OneOfType(o *OneOf, state *APIState) string - // BodyAccessor returns a string representation of the accessor used to - // get the body out of a request. For instance this might return `.Body()`. - BodyAccessor(m *Method, state *APIState) string - // HTTPPathFmt returns a format string used for adding path arguments to a - // URL. The replacements should align in both order and value from what is - // returned from HTTPPathArgs. - HTTPPathFmt(m *PathInfo, state *APIState) string - // HTTPPathArgs returns a string representation of the path arguments. This - // should be used in conjunction with HTTPPathFmt. An example return value - // might be `, req.PathParam()` - HTTPPathArgs(h *PathInfo, state *APIState) []string - // QueryParams returns key-value pairs of name to accessor for query params. - // An example return value might be - // `&Pair{Key: "secretId", Value: "req.SecretId()"}` - QueryParams(m *Method, state *APIState) []*Field - // ToSnake converts a symbol name to `snake_case`, applying any mangling - // required by the language, e.g., to avoid clashes with reserved words. - ToSnake(string) string - // ToSnakeNoMangling converts a symbol name to `snake_case`, without any - // mangling to avoid reserved words. This is useful when the template is - // already going to mangle the name, e.g., by adding a prefix or suffix. - // Since the templates are language specific, their authors can determine - // when to use `ToSnake` or `ToSnakeNoMangling`. - ToSnakeNoMangling(string) string - // ToPascal converts a symbol name to `PascalCase`, applying any mangling - // required by the language, e.g., to avoid clashes with reserved words. - ToPascal(string) string - // ToCamel converts a symbol name to `camelCase` (sometimes called - // "lowercase CamelCase"), applying any mangling required by the language, - // e.g., to avoid clashes with reserved words. - ToCamel(string) string - // Reformat ${Lang}Doc comments according to the language-specific rules. - // For example, - // - The protos in googleapis include cross-references in the format - // `[Foo][proto.package.name.Foo]`, this should become links to the - // language entities, in the language documentation. - // - Rust requires a `norust` annotation in all blockquotes, that is, - // any ```-sections. Without this annotation Rustdoc assumes the - // blockquote is an Rust code snippet and attempts to compile it. - FormatDocComments(string) []string - // Returns a extra set of lines to insert in the module file. - // The format of these lines is specific to each language. - RequiredPackages() []string - // The package name in the destination language. May be empty, some - // languages do not have a package manager. - PackageName(api *API) string - // Validate an API, some codecs impose restrictions on the input API. - Validate(api *API) error - // The year when this package was first generated. - CopyrightYear() string - // Pass language-specific information from the Codec to the template engine. - // Prefer using specific methods when the information is applicable to most - // (or many) languages. Use this method when the information is application - // to only one language. - AdditionalContext() any - // Imports to add. - Imports() []string -} - type ParserOptions struct { // The location where the specification can be found. Source string @@ -147,9 +46,9 @@ type CodecOptions struct { // GenerateRequest used to generate clients. type GenerateRequest struct { // The in memory representation of a parsed input. - API *API + API *api.API // An adapter to transform values into language idiomatic representations. - Codec LanguageCodec + Codec api.LanguageCodec // OutDir is the path to the output directory. OutDir string // Template directory diff --git a/generator/internal/genclient/templatedata.go b/generator/internal/genclient/templatedata.go index 0bb3f7314..3b98b2aa2 100644 --- a/generator/internal/genclient/templatedata.go +++ b/generator/internal/genclient/templatedata.go @@ -17,6 +17,7 @@ package genclient import ( "strings" + "github.com/googleapis/google-cloud-rust/generator/internal/api" "github.com/iancoleman/strcase" ) @@ -26,7 +27,7 @@ import ( // the [templateData.Services] method. templateData uses the raw input of the // [API] and uses a [lang.Codec] to transform the input into language // idiomatic representations. -func newTemplateData(model *API, codec LanguageCodec) *templateData { +func newTemplateData(model *api.API, codec api.LanguageCodec) *templateData { codec.LoadWellKnownTypes(model.State) return &templateData{ s: model, @@ -35,8 +36,8 @@ func newTemplateData(model *API, codec LanguageCodec) *templateData { } type templateData struct { - s *API - c LanguageCodec + s *api.API + c api.LanguageCodec } func (t *templateData) Name() string { @@ -90,7 +91,7 @@ func (t templateData) DefaultHost() string { } func (t *templateData) Services() []*service { - return mapSlice(t.s.Services, func(s *Service) *service { + return mapSlice(t.s.Services, func(s *api.Service) *service { return &service{ s: s, c: t.c, @@ -100,7 +101,7 @@ func (t *templateData) Services() []*service { } func (t *templateData) Messages() []*message { - return mapSlice(t.s.Messages, func(m *Message) *message { + return mapSlice(t.s.Messages, func(m *api.Message) *message { return &message{ s: m, c: t.c, @@ -115,13 +116,13 @@ func (t *templateData) NameToLower() string { // service represents a service in an API. type service struct { - s *Service - c LanguageCodec - state *APIState + s *api.Service + c api.LanguageCodec + state *api.APIState } func (s *service) Methods() []*method { - return mapSlice(s.s.Methods, func(m *Method) *method { + return mapSlice(s.s.Methods, func(m *api.Method) *method { return &method{ s: m, c: s.c, @@ -164,9 +165,9 @@ func (s *service) DefaultHost() string { // method defines a RPC belonging to a Service. type method struct { - s *Method - c LanguageCodec - state *APIState + s *api.Method + c api.LanguageCodec + state *api.APIState } // NameToSnake converts a Name to snake_case. @@ -212,7 +213,7 @@ func (m *method) HTTPPathArgs() []string { } func (m *method) QueryParams() []*field { - return mapSlice(m.c.QueryParams(m.s, m.state), func(s *Field) *field { + return mapSlice(m.c.QueryParams(m.s, m.state), func(s *api.Field) *field { return &field{ s: s, c: m.c, @@ -231,13 +232,13 @@ func (m *method) BodyAccessor() string { // message defines a message used in request or response handling. type message struct { - s *Message - c LanguageCodec - state *APIState + s *api.Message + c api.LanguageCodec + state *api.APIState } func (m *message) Fields() []*field { - return mapSlice(m.s.Fields, func(s *Field) *field { + return mapSlice(m.s.Fields, func(s *api.Field) *field { return &field{ s: s, c: m.c, @@ -249,10 +250,10 @@ func (m *message) Fields() []*field { // BasicFields returns all fields associated with a message that are not apart // of a explicit one-ofs. func (m *message) BasicFields() []*field { - filtered := filterSlice(m.s.Fields, func(s *Field) bool { + filtered := filterSlice(m.s.Fields, func(s *api.Field) bool { return !s.IsOneOf }) - return mapSlice(filtered, func(s *Field) *field { + return mapSlice(filtered, func(s *api.Field) *field { return &field{ s: s, c: m.c, @@ -264,7 +265,7 @@ func (m *message) BasicFields() []*field { // ExplicitOneOfs returns a slice of all explicit one-ofs. Notably this leaves // out proto3 optional fields which are all considered one-ofs in proto. func (m *message) ExplicitOneOfs() []*oneOf { - return mapSlice(m.s.OneOfs, func(s *OneOf) *oneOf { + return mapSlice(m.s.OneOfs, func(s *api.OneOf) *oneOf { return &oneOf{ s: s, c: m.c, @@ -274,7 +275,7 @@ func (m *message) ExplicitOneOfs() []*oneOf { } func (m *message) NestedMessages() []*message { - return mapSlice(m.s.Messages, func(s *Message) *message { + return mapSlice(m.s.Messages, func(s *api.Message) *message { return &message{ s: s, c: m.c, @@ -284,7 +285,7 @@ func (m *message) NestedMessages() []*message { } func (m *message) Enums() []*enum { - return mapSlice(m.s.Enums, func(s *Enum) *enum { + return mapSlice(m.s.Enums, func(s *api.Enum) *enum { return &enum{ s: s, c: m.c, @@ -332,9 +333,9 @@ func (m *message) IsMap() bool { } type enum struct { - s *Enum - c LanguageCodec - state *APIState + s *api.Enum + c api.LanguageCodec + state *api.APIState } func (e *enum) Name() string { @@ -350,7 +351,7 @@ func (e *enum) DocLines() []string { } func (e *enum) Values() []*enumValue { - return mapSlice(e.s.Values, func(s *EnumValue) *enumValue { + return mapSlice(e.s.Values, func(s *api.EnumValue) *enumValue { return &enumValue{ s: s, e: e.s, @@ -361,10 +362,10 @@ func (e *enum) Values() []*enumValue { } type enumValue struct { - s *EnumValue - e *Enum - c LanguageCodec - state *APIState + s *api.EnumValue + e *api.Enum + c api.LanguageCodec + state *api.APIState } func (e *enumValue) DocLines() []string { @@ -385,9 +386,9 @@ func (e *enumValue) EnumType() string { // field defines a field in a Message. type field struct { - s *Field - c LanguageCodec - state *APIState + s *api.Field + c api.LanguageCodec + state *api.APIState } // NameToSnake converts a Name to snake_case. @@ -429,9 +430,9 @@ func (f *field) AsQueryParameter() string { } type oneOf struct { - s *OneOf - c LanguageCodec - state *APIState + s *api.OneOf + c api.LanguageCodec + state *api.APIState } func (o *oneOf) NameToPascal() string { @@ -455,7 +456,7 @@ func (o *oneOf) DocLines() []string { } func (o *oneOf) Fields() []*field { - return mapSlice(o.s.Fields, func(s *Field) *field { + return mapSlice(o.s.Fields, func(s *api.Field) *field { return &field{ s: s, c: o.c, diff --git a/generator/internal/language/api_test.go b/generator/internal/language/api_test.go index fe4eb532d..98e251d65 100644 --- a/generator/internal/language/api_test.go +++ b/generator/internal/language/api_test.go @@ -17,14 +17,14 @@ package language import ( "strings" - "github.com/googleapis/google-cloud-rust/generator/internal/genclient" + "github.com/googleapis/google-cloud-rust/generator/internal/api" ) -func newTestAPI(messages []*genclient.Message, enums []*genclient.Enum, services []*genclient.Service) *genclient.API { - state := &genclient.APIState{ - MessageByID: make(map[string]*genclient.Message), - EnumByID: make(map[string]*genclient.Enum), - ServiceByID: make(map[string]*genclient.Service), +func newTestAPI(messages []*api.Message, enums []*api.Enum, services []*api.Service) *api.API { + state := &api.APIState{ + MessageByID: make(map[string]*api.Message), + EnumByID: make(map[string]*api.Enum), + ServiceByID: make(map[string]*api.Service), } for _, m := range messages { state.MessageByID[m.ID] = m @@ -51,7 +51,7 @@ func newTestAPI(messages []*genclient.Message, enums []*genclient.Enum, services } } - return &genclient.API{ + return &api.API{ Name: "Test", Messages: messages, Enums: enums, diff --git a/generator/internal/language/golang.go b/generator/internal/language/golang.go index a1554a516..0a1feddb8 100644 --- a/generator/internal/language/golang.go +++ b/generator/internal/language/golang.go @@ -21,6 +21,7 @@ import ( "time" "unicode" + "github.com/googleapis/google-cloud-rust/generator/internal/api" "github.com/googleapis/google-cloud-rust/generator/internal/genclient" "github.com/iancoleman/strcase" ) @@ -74,13 +75,13 @@ type GoImport struct { Name string } -func (c *GoCodec) LoadWellKnownTypes(s *genclient.APIState) { - timestamp := &genclient.Message{ +func (c *GoCodec) LoadWellKnownTypes(s *api.APIState) { + timestamp := &api.Message{ ID: ".google.protobuf.Timestamp", Name: "Time", Package: "time", } - duration := &genclient.Message{ + duration := &api.Message{ ID: ".google.protobuf.Duration", Name: "Duration", Package: "time", @@ -89,24 +90,24 @@ func (c *GoCodec) LoadWellKnownTypes(s *genclient.APIState) { s.MessageByID[duration.ID] = duration } -func (*GoCodec) FieldAttributes(*genclient.Field, *genclient.APIState) []string { +func (*GoCodec) FieldAttributes(*api.Field, *api.APIState) []string { return []string{} } -func (c *GoCodec) FieldType(f *genclient.Field, state *genclient.APIState) string { +func (c *GoCodec) FieldType(f *api.Field, state *api.APIState) string { var out string switch f.Typez { - case genclient.STRING_TYPE: + case api.STRING_TYPE: out = "string" - case genclient.INT64_TYPE: + case api.INT64_TYPE: out = "int64" - case genclient.INT32_TYPE: + case api.INT32_TYPE: out = "int32" - case genclient.BOOL_TYPE: + case api.BOOL_TYPE: out = "bool" - case genclient.BYTES_TYPE: + case api.BYTES_TYPE: out = "[]byte" - case genclient.MESSAGE_TYPE: + case api.MESSAGE_TYPE: m, ok := state.MessageByID[f.TypezID] if !ok { slog.Error("unable to lookup type", "id", f.TypezID) @@ -119,7 +120,7 @@ func (c *GoCodec) FieldType(f *genclient.Field, state *genclient.APIState) strin break } out = "*" + c.MessageName(m, state) - case genclient.ENUM_TYPE: + case api.ENUM_TYPE: e, ok := state.EnumByID[f.TypezID] if !ok { slog.Error("unable to lookup type", "id", f.TypezID) @@ -132,7 +133,7 @@ func (c *GoCodec) FieldType(f *genclient.Field, state *genclient.APIState) strin return out } -func (c *GoCodec) AsQueryParameter(f *genclient.Field, state *genclient.APIState) string { +func (c *GoCodec) AsQueryParameter(f *api.Field, state *api.APIState) string { return fmt.Sprintf("req.%s.to_str()", c.ToCamel(f.Name)) } @@ -140,7 +141,7 @@ func (c *GoCodec) TemplateDir() string { return "go" } -func (c *GoCodec) MethodInOutTypeName(id string, s *genclient.APIState) string { +func (c *GoCodec) MethodInOutTypeName(id string, s *api.APIState) string { if id == "" { return "" } @@ -152,11 +153,11 @@ func (c *GoCodec) MethodInOutTypeName(id string, s *genclient.APIState) string { return strcase.ToCamel(m.Name) } -func (*GoCodec) MessageAttributes(*genclient.Message, *genclient.APIState) []string { +func (*GoCodec) MessageAttributes(*api.Message, *api.APIState) []string { return []string{} } -func (c *GoCodec) MessageName(m *genclient.Message, state *genclient.APIState) string { +func (c *GoCodec) MessageName(m *api.Message, state *api.APIState) string { if m.Parent != nil { return c.MessageName(m.Parent, state) + "_" + strcase.ToCamel(m.Name) } @@ -166,37 +167,37 @@ func (c *GoCodec) MessageName(m *genclient.Message, state *genclient.APIState) s return c.ToPascal(m.Name) } -func (c *GoCodec) FQMessageName(m *genclient.Message, state *genclient.APIState) string { +func (c *GoCodec) FQMessageName(m *api.Message, state *api.APIState) string { return c.MessageName(m, state) } -func (c *GoCodec) EnumName(e *genclient.Enum, state *genclient.APIState) string { +func (c *GoCodec) EnumName(e *api.Enum, state *api.APIState) string { if e.Parent != nil { return c.MessageName(e.Parent, state) + "_" + strcase.ToCamel(e.Name) } return strcase.ToCamel(e.Name) } -func (c *GoCodec) FQEnumName(e *genclient.Enum, state *genclient.APIState) string { +func (c *GoCodec) FQEnumName(e *api.Enum, state *api.APIState) string { return c.EnumName(e, state) } -func (c *GoCodec) EnumValueName(e *genclient.EnumValue, state *genclient.APIState) string { +func (c *GoCodec) EnumValueName(e *api.EnumValue, state *api.APIState) string { if e.Parent.Parent != nil { return c.MessageName(e.Parent.Parent, state) + "_" + strings.ToUpper(e.Name) } return strings.ToUpper(e.Name) } -func (c *GoCodec) FQEnumValueName(v *genclient.EnumValue, state *genclient.APIState) string { +func (c *GoCodec) FQEnumValueName(v *api.EnumValue, state *api.APIState) string { return c.EnumValueName(v, state) } -func (c *GoCodec) OneOfType(o *genclient.OneOf, _ *genclient.APIState) string { +func (c *GoCodec) OneOfType(o *api.OneOf, _ *api.APIState) string { panic("not needed for Go") } -func (c *GoCodec) BodyAccessor(m *genclient.Method, state *genclient.APIState) string { +func (c *GoCodec) BodyAccessor(m *api.Method, state *api.APIState) string { if m.PathInfo.BodyFieldPath == "*" { // no accessor needed, use the whole request return "" @@ -204,7 +205,7 @@ func (c *GoCodec) BodyAccessor(m *genclient.Method, state *genclient.APIState) s return "." + strcase.ToCamel(m.PathInfo.BodyFieldPath) } -func (c *GoCodec) HTTPPathFmt(m *genclient.PathInfo, state *genclient.APIState) string { +func (c *GoCodec) HTTPPathFmt(m *api.PathInfo, state *api.APIState) string { fmt := "" for _, segment := range m.PathTemplate { if segment.Literal != nil { @@ -218,7 +219,7 @@ func (c *GoCodec) HTTPPathFmt(m *genclient.PathInfo, state *genclient.APIState) return fmt } -func (c *GoCodec) HTTPPathArgs(h *genclient.PathInfo, state *genclient.APIState) []string { +func (c *GoCodec) HTTPPathArgs(h *api.PathInfo, state *api.APIState) []string { var args []string // TODO(codyoss): https://github.com/googleapis/google-cloud-rust/issues/34 for _, segment := range h.PathTemplate { @@ -230,14 +231,14 @@ func (c *GoCodec) HTTPPathArgs(h *genclient.PathInfo, state *genclient.APIState) return args } -func (c *GoCodec) QueryParams(m *genclient.Method, state *genclient.APIState) []*genclient.Field { +func (c *GoCodec) QueryParams(m *api.Method, state *api.APIState) []*api.Field { msg, ok := state.MessageByID[m.InputTypeID] if !ok { slog.Error("unable to lookup type", "id", m.InputTypeID) return nil } - var queryParams []*genclient.Field + var queryParams []*api.Field for _, field := range msg.Fields { if !m.PathInfo.QueryParameters[field.JSONName] { continue @@ -282,7 +283,7 @@ func (c *GoCodec) CopyrightYear() string { return c.GenerationYear } -func (c *GoCodec) PackageName(api *genclient.API) string { +func (c *GoCodec) PackageName(api *api.API) string { if len(c.PackageNameOverride) > 0 { return c.PackageNameOverride } @@ -306,7 +307,7 @@ func (c *GoCodec) validatePackageName(newPackage, elementName string) error { c.SourceSpecificationPackageName, newPackage, elementName) } -func (c *GoCodec) Validate(api *genclient.API) error { +func (c *GoCodec) Validate(api *api.API) error { // Set the source package. We should always take the first service registered // as the source package. Services with mixes will register those after the // source package. diff --git a/generator/internal/language/golang_test.go b/generator/internal/language/golang_test.go index c636a7426..e28839008 100644 --- a/generator/internal/language/golang_test.go +++ b/generator/internal/language/golang_test.go @@ -18,7 +18,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/googleapis/google-cloud-rust/generator/internal/genclient" + "github.com/googleapis/google-cloud-rust/generator/internal/api" ) type goCaseConvertTest struct { @@ -58,25 +58,25 @@ func TestGo_ToPascal(t *testing.T) { } func TestGo_MessageNames(t *testing.T) { - message := &genclient.Message{ + message := &api.Message{ Name: "Replication", ID: "..Replication", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "automatic", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: "..Automatic", Optional: true, Repeated: false, }, }, } - nested := &genclient.Message{ + nested := &api.Message{ Name: "Automatic", ID: "..Replication.Automatic", } - api := newTestAPI([]*genclient.Message{message, nested}, []*genclient.Enum{}, []*genclient.Service{}) + api := newTestAPI([]*api.Message{message, nested}, []*api.Enum{}, []*api.Service{}) c := &GoCodec{} if got := c.MessageName(message, api.State); got != "Replication" { @@ -95,25 +95,25 @@ func TestGo_MessageNames(t *testing.T) { } func TestGo_EnumNames(t *testing.T) { - message := &genclient.Message{ + message := &api.Message{ Name: "SecretVersion", ID: "..SecretVersion", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "automatic", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: "..Automatic", Optional: true, Repeated: false, }, }, } - nested := &genclient.Enum{ + nested := &api.Enum{ Name: "State", ID: "..SecretVersion.State", } - api := newTestAPI([]*genclient.Message{message}, []*genclient.Enum{nested}, []*genclient.Service{}) + api := newTestAPI([]*api.Message{message}, []*api.Enum{nested}, []*api.Service{}) c := &GoCodec{} if got := c.EnumName(nested, api.State); got != "SecretVersion_State" { @@ -171,9 +171,9 @@ Maybe they wanted to show some JSON: func TestGo_Validate(t *testing.T) { api := newTestAPI( - []*genclient.Message{{Name: "m1", Package: "p1"}}, - []*genclient.Enum{{Name: "e1", Package: "p1"}}, - []*genclient.Service{{Name: "s1", Package: "p1"}}) + []*api.Message{{Name: "m1", Package: "p1"}}, + []*api.Enum{{Name: "e1", Package: "p1"}}, + []*api.Service{{Name: "s1", Package: "p1"}}) c := &GoCodec{} if err := c.Validate(api); err != nil { t.Errorf("unexpected error in API validation %q", err) @@ -184,30 +184,30 @@ func TestGo_Validate(t *testing.T) { } func TestGo_ValidateMessageMismatch(t *testing.T) { - api := newTestAPI( - []*genclient.Message{{Name: "m1", Package: "p1"}, {Name: "m2", Package: "p2"}}, - []*genclient.Enum{{Name: "e1", Package: "p1"}}, - []*genclient.Service{{Name: "s1", Package: "p1"}}) + test := newTestAPI( + []*api.Message{{Name: "m1", Package: "p1"}, {Name: "m2", Package: "p2"}}, + []*api.Enum{{Name: "e1", Package: "p1"}}, + []*api.Service{{Name: "s1", Package: "p1"}}) c := &GoCodec{} - if err := c.Validate(api); err == nil { + if err := c.Validate(test); err == nil { t.Errorf("expected an error in API validation got=%s", c.SourceSpecificationPackageName) } - api = newTestAPI( - []*genclient.Message{{Name: "m1", Package: "p1"}}, - []*genclient.Enum{{Name: "e1", Package: "p1"}, {Name: "e2", Package: "p2"}}, - []*genclient.Service{{Name: "s1", Package: "p1"}}) + test = newTestAPI( + []*api.Message{{Name: "m1", Package: "p1"}}, + []*api.Enum{{Name: "e1", Package: "p1"}, {Name: "e2", Package: "p2"}}, + []*api.Service{{Name: "s1", Package: "p1"}}) c = &GoCodec{} - if err := c.Validate(api); err == nil { + if err := c.Validate(test); err == nil { t.Errorf("expected an error in API validation got=%s", c.SourceSpecificationPackageName) } - api = newTestAPI( - []*genclient.Message{{Name: "m1", Package: "p1"}}, - []*genclient.Enum{{Name: "e1", Package: "p1"}}, - []*genclient.Service{{Name: "s1", Package: "p1"}, {Name: "s2", Package: "p2"}}) + test = newTestAPI( + []*api.Message{{Name: "m1", Package: "p1"}}, + []*api.Enum{{Name: "e1", Package: "p1"}}, + []*api.Service{{Name: "s1", Package: "p1"}, {Name: "s2", Package: "p2"}}) c = &GoCodec{} - if err := c.Validate(api); err == nil { + if err := c.Validate(test); err == nil { t.Errorf("expected an error in API validation got=%s", c.SourceSpecificationPackageName) } } diff --git a/generator/internal/language/rust.go b/generator/internal/language/rust.go index b8e1564f3..831e40396 100644 --- a/generator/internal/language/rust.go +++ b/generator/internal/language/rust.go @@ -24,6 +24,7 @@ import ( "time" "unicode" + "github.com/googleapis/google-cloud-rust/generator/internal/api" "github.com/googleapis/google-cloud-rust/generator/internal/genclient" "github.com/iancoleman/strcase" ) @@ -154,9 +155,9 @@ type RustPackage struct { Features []string } -func (c *RustCodec) LoadWellKnownTypes(s *genclient.APIState) { +func (c *RustCodec) LoadWellKnownTypes(s *api.APIState) { // TODO(#77) - replace these placeholders with real types - wellKnown := []*genclient.Message{ + wellKnown := []*api.Message{ { ID: ".google.protobuf.Any", Name: "Any", @@ -188,38 +189,38 @@ func (c *RustCodec) LoadWellKnownTypes(s *genclient.APIState) { } } -func ScalarFieldType(f *genclient.Field) string { +func ScalarFieldType(f *api.Field) string { var out string switch f.Typez { - case genclient.DOUBLE_TYPE: + case api.DOUBLE_TYPE: out = "f64" - case genclient.FLOAT_TYPE: + case api.FLOAT_TYPE: out = "f32" - case genclient.INT64_TYPE: + case api.INT64_TYPE: out = "i64" - case genclient.UINT64_TYPE: + case api.UINT64_TYPE: out = "u64" - case genclient.INT32_TYPE: + case api.INT32_TYPE: out = "i32" - case genclient.FIXED64_TYPE: + case api.FIXED64_TYPE: out = "u64" - case genclient.FIXED32_TYPE: + case api.FIXED32_TYPE: out = "u32" - case genclient.BOOL_TYPE: + case api.BOOL_TYPE: out = "bool" - case genclient.STRING_TYPE: + case api.STRING_TYPE: out = "String" - case genclient.BYTES_TYPE: + case api.BYTES_TYPE: out = "bytes::Bytes" - case genclient.UINT32_TYPE: + case api.UINT32_TYPE: out = "u32" - case genclient.SFIXED32_TYPE: + case api.SFIXED32_TYPE: out = "i32" - case genclient.SFIXED64_TYPE: + case api.SFIXED64_TYPE: out = "i64" - case genclient.SINT32_TYPE: + case api.SINT32_TYPE: out = "i32" - case genclient.SINT64_TYPE: + case api.SINT64_TYPE: out = "i64" default: @@ -229,22 +230,22 @@ func ScalarFieldType(f *genclient.Field) string { return out } -func (c *RustCodec) fieldFormatter(typez genclient.Typez) string { +func (c *RustCodec) fieldFormatter(typez api.Typez) string { switch typez { - case genclient.INT64_TYPE, - genclient.UINT64_TYPE, - genclient.FIXED64_TYPE, - genclient.SFIXED64_TYPE, - genclient.SINT64_TYPE: + case api.INT64_TYPE, + api.UINT64_TYPE, + api.FIXED64_TYPE, + api.SFIXED64_TYPE, + api.SINT64_TYPE: return "serde_with::DisplayFromStr" - case genclient.BYTES_TYPE: + case api.BYTES_TYPE: return "serde_with::base64::Base64" default: return "_" } } -func (c *RustCodec) fieldBaseAttributes(f *genclient.Field) []string { +func (c *RustCodec) fieldBaseAttributes(f *api.Field) []string { if f.Synthetic { return []string{`#[serde(skip)]`} } @@ -254,43 +255,43 @@ func (c *RustCodec) fieldBaseAttributes(f *genclient.Field) []string { return []string{} } -func (c *RustCodec) wrapperFieldAttributes(f *genclient.Field, defaultAttributes []string) []string { +func (c *RustCodec) wrapperFieldAttributes(f *api.Field, defaultAttributes []string) []string { var formatter string switch f.TypezID { case ".google.protobuf.BytesValue": - formatter = c.fieldFormatter(genclient.BYTES_TYPE) + formatter = c.fieldFormatter(api.BYTES_TYPE) case ".google.protobuf.UInt64Value": - formatter = c.fieldFormatter(genclient.UINT64_TYPE) + formatter = c.fieldFormatter(api.UINT64_TYPE) case ".google.protobuf.Int64Value": - formatter = c.fieldFormatter(genclient.INT64_TYPE) + formatter = c.fieldFormatter(api.INT64_TYPE) default: return defaultAttributes } return []string{fmt.Sprintf(`#[serde_as(as = "Option<%s>")]`, formatter)} } -func (c *RustCodec) FieldAttributes(f *genclient.Field, state *genclient.APIState) []string { +func (c *RustCodec) FieldAttributes(f *api.Field, state *api.APIState) []string { attributes := c.fieldBaseAttributes(f) switch f.Typez { - case genclient.DOUBLE_TYPE, - genclient.FLOAT_TYPE, - genclient.INT32_TYPE, - genclient.FIXED32_TYPE, - genclient.BOOL_TYPE, - genclient.STRING_TYPE, - genclient.UINT32_TYPE, - genclient.SFIXED32_TYPE, - genclient.SINT32_TYPE, - genclient.ENUM_TYPE, - genclient.GROUP_TYPE: + case api.DOUBLE_TYPE, + api.FLOAT_TYPE, + api.INT32_TYPE, + api.FIXED32_TYPE, + api.BOOL_TYPE, + api.STRING_TYPE, + api.UINT32_TYPE, + api.SFIXED32_TYPE, + api.SINT32_TYPE, + api.ENUM_TYPE, + api.GROUP_TYPE: return attributes - case genclient.INT64_TYPE, - genclient.UINT64_TYPE, - genclient.FIXED64_TYPE, - genclient.SFIXED64_TYPE, - genclient.SINT64_TYPE, - genclient.BYTES_TYPE: + case api.INT64_TYPE, + api.UINT64_TYPE, + api.FIXED64_TYPE, + api.SFIXED64_TYPE, + api.SINT64_TYPE, + api.BYTES_TYPE: formatter := c.fieldFormatter(f.Typez) if f.Optional { return append(attributes, fmt.Sprintf(`#[serde_as(as = "Option<%s>")]`, formatter)) @@ -300,10 +301,10 @@ func (c *RustCodec) FieldAttributes(f *genclient.Field, state *genclient.APIStat } return append(attributes, fmt.Sprintf(`#[serde_as(as = "%s")]`, formatter)) - case genclient.MESSAGE_TYPE: + case api.MESSAGE_TYPE: if message, ok := state.MessageByID[f.TypezID]; ok && message.IsMap { attributes = append(attributes, `#[serde(skip_serializing_if = "std::collections::HashMap::is_empty")]`) - var key, value *genclient.Field + var key, value *api.Field for _, f := range message.Fields { switch f.Name { case "key": @@ -332,7 +333,7 @@ func (c *RustCodec) FieldAttributes(f *genclient.Field, state *genclient.APIStat } } -func (c *RustCodec) FieldType(f *genclient.Field, state *genclient.APIState) string { +func (c *RustCodec) FieldType(f *api.Field, state *api.APIState) string { if f.IsOneOf { return c.wrapOneOfField(f, c.baseFieldType(f, state)) } @@ -346,8 +347,8 @@ func (c *RustCodec) FieldType(f *genclient.Field, state *genclient.APIState) str } // Returns the field type, ignoring any repeated or optional attributes. -func (c *RustCodec) baseFieldType(f *genclient.Field, state *genclient.APIState) string { - if f.Typez == genclient.MESSAGE_TYPE { +func (c *RustCodec) baseFieldType(f *api.Field, state *api.APIState) string { + if f.Typez == api.MESSAGE_TYPE { m, ok := state.MessageByID[f.TypezID] if !ok { slog.Error("unable to lookup type", "id", f.TypezID) @@ -359,14 +360,14 @@ func (c *RustCodec) baseFieldType(f *genclient.Field, state *genclient.APIState) return "std::collections::HashMap<" + key + "," + val + ">" } return c.FQMessageName(m, state) - } else if f.Typez == genclient.ENUM_TYPE { + } else if f.Typez == api.ENUM_TYPE { e, ok := state.EnumByID[f.TypezID] if !ok { slog.Error("unable to lookup type", "id", f.TypezID) return "" } return c.FQEnumName(e, state) - } else if f.Typez == genclient.GROUP_TYPE { + } else if f.Typez == api.GROUP_TYPE { slog.Error("TODO(#39) - better handling of `oneof` fields") return "" } @@ -374,15 +375,15 @@ func (c *RustCodec) baseFieldType(f *genclient.Field, state *genclient.APIState) } -func (c *RustCodec) wrapOneOfField(f *genclient.Field, value string) string { - if f.Typez == genclient.MESSAGE_TYPE { +func (c *RustCodec) wrapOneOfField(f *api.Field, value string) string { + if f.Typez == api.MESSAGE_TYPE { return fmt.Sprintf("(%s)", value) } return fmt.Sprintf("{ %s: %s }", c.ToSnake(f.Name), value) } -func (c *RustCodec) AsQueryParameter(f *genclient.Field, state *genclient.APIState) string { - if f.Typez == genclient.MESSAGE_TYPE { +func (c *RustCodec) AsQueryParameter(f *api.Field, state *api.APIState) string { + if f.Typez == api.MESSAGE_TYPE { // Query parameters in nested messages are first converted to a // `serde_json::Value`` and then recursively merged into the request // query. The conversion to `serde_json::Value` is expensive, but very @@ -400,7 +401,7 @@ func (c *RustCodec) TemplateDir() string { return "rust/crate" } -func (c *RustCodec) MethodInOutTypeName(id string, state *genclient.APIState) string { +func (c *RustCodec) MethodInOutTypeName(id string, state *api.APIState) string { if id == "" { return "" } @@ -428,7 +429,7 @@ func (c *RustCodec) rustPackage(packageName string) string { return mapped.Name + "::model" } -func (c *RustCodec) MessageAttributes(*genclient.Message, *genclient.APIState) []string { +func (c *RustCodec) MessageAttributes(*api.Message, *api.APIState) []string { serde := `#[serde(default, rename_all = "camelCase")]` if !c.DeserializeWithdDefaults { serde = `#[serde(rename_all = "camelCase")]` @@ -441,11 +442,11 @@ func (c *RustCodec) MessageAttributes(*genclient.Message, *genclient.APIState) [ } } -func (c *RustCodec) MessageName(m *genclient.Message, state *genclient.APIState) string { +func (c *RustCodec) MessageName(m *api.Message, state *api.APIState) string { return c.ToPascal(m.Name) } -func (c *RustCodec) messageScopeName(m *genclient.Message, childPackageName string) string { +func (c *RustCodec) messageScopeName(m *api.Message, childPackageName string) string { if m == nil { return c.rustPackage(childPackageName) } @@ -455,37 +456,37 @@ func (c *RustCodec) messageScopeName(m *genclient.Message, childPackageName stri return c.messageScopeName(m.Parent, m.Package) + "::" + c.ToSnake(m.Name) } -func (c *RustCodec) enumScopeName(e *genclient.Enum) string { +func (c *RustCodec) enumScopeName(e *api.Enum) string { return c.messageScopeName(e.Parent, "") } -func (c *RustCodec) FQMessageName(m *genclient.Message, _ *genclient.APIState) string { +func (c *RustCodec) FQMessageName(m *api.Message, _ *api.APIState) string { return c.messageScopeName(m.Parent, m.Package) + "::" + c.ToPascal(m.Name) } -func (c *RustCodec) EnumName(e *genclient.Enum, state *genclient.APIState) string { +func (c *RustCodec) EnumName(e *api.Enum, state *api.APIState) string { return c.ToPascal(e.Name) } -func (c *RustCodec) FQEnumName(e *genclient.Enum, _ *genclient.APIState) string { +func (c *RustCodec) FQEnumName(e *api.Enum, _ *api.APIState) string { return c.messageScopeName(e.Parent, "") + "::" + c.ToPascal(e.Name) } -func (c *RustCodec) EnumValueName(e *genclient.EnumValue, _ *genclient.APIState) string { +func (c *RustCodec) EnumValueName(e *api.EnumValue, _ *api.APIState) string { // The Protobuf naming convention is to use SCREAMING_SNAKE_CASE, we do not // need to change anything for Rust return rustEscapeKeyword(e.Name) } -func (c *RustCodec) FQEnumValueName(v *genclient.EnumValue, state *genclient.APIState) string { +func (c *RustCodec) FQEnumValueName(v *api.EnumValue, state *api.APIState) string { return fmt.Sprintf("%s::%s::%s", c.enumScopeName(v.Parent), c.ToSnake(v.Parent.Name), c.EnumValueName(v, state)) } -func (c *RustCodec) OneOfType(o *genclient.OneOf, _ *genclient.APIState) string { +func (c *RustCodec) OneOfType(o *api.OneOf, _ *api.APIState) string { return c.messageScopeName(o.Parent, "") + "::" + c.ToPascal(o.Name) } -func (c *RustCodec) BodyAccessor(m *genclient.Method, state *genclient.APIState) string { +func (c *RustCodec) BodyAccessor(m *api.Method, state *api.APIState) string { if m.PathInfo.BodyFieldPath == "*" { // no accessor needed, use the whole request return "" @@ -493,7 +494,7 @@ func (c *RustCodec) BodyAccessor(m *genclient.Method, state *genclient.APIState) return "." + c.ToSnake(m.PathInfo.BodyFieldPath) } -func (c *RustCodec) HTTPPathFmt(m *genclient.PathInfo, state *genclient.APIState) string { +func (c *RustCodec) HTTPPathFmt(m *api.PathInfo, state *api.APIState) string { fmt := "" for _, segment := range m.PathTemplate { if segment.Literal != nil { @@ -550,7 +551,7 @@ func (c *RustCodec) derefFieldPath(fieldPath string) string { return unwrap } -func (c *RustCodec) HTTPPathArgs(h *genclient.PathInfo, state *genclient.APIState) []string { +func (c *RustCodec) HTTPPathArgs(h *api.PathInfo, state *api.APIState) []string { var args []string for _, arg := range h.PathTemplate { if arg.FieldPath != nil { @@ -560,14 +561,14 @@ func (c *RustCodec) HTTPPathArgs(h *genclient.PathInfo, state *genclient.APIStat return args } -func (c *RustCodec) QueryParams(m *genclient.Method, state *genclient.APIState) []*genclient.Field { +func (c *RustCodec) QueryParams(m *api.Method, state *api.APIState) []*api.Field { msg, ok := state.MessageByID[m.InputTypeID] if !ok { slog.Error("unable to lookup request type", "id", m.InputTypeID) return nil } - var queryParams []*genclient.Field + var queryParams []*api.Field for _, field := range msg.Fields { if !m.PathInfo.QueryParameters[field.Name] { continue @@ -667,7 +668,7 @@ func (c *RustCodec) CopyrightYear() string { return c.GenerationYear } -func (c *RustCodec) PackageName(api *genclient.API) string { +func (c *RustCodec) PackageName(api *api.API) string { if len(c.PackageNameOverride) > 0 { return c.PackageNameOverride } @@ -694,7 +695,7 @@ func (c *RustCodec) validatePackageName(newPackage, elementName string) error { c.SourceSpecificationPackageName, newPackage, elementName) } -func (c *RustCodec) Validate(api *genclient.API) error { +func (c *RustCodec) Validate(api *api.API) error { // Set the source package. We should always take the first service registered // as the source package. Services with mixins will register those after the // source package. diff --git a/generator/internal/language/rust_test.go b/generator/internal/language/rust_test.go index 95711be51..b01e6c4c6 100644 --- a/generator/internal/language/rust_test.go +++ b/generator/internal/language/rust_test.go @@ -21,6 +21,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" + "github.com/googleapis/google-cloud-rust/generator/internal/api" "github.com/googleapis/google-cloud-rust/generator/internal/genclient" ) @@ -141,21 +142,21 @@ func TestRust_PackageName(t *testing.T) { Options: map[string]string{ "package-name-override": "test-only-overridden", }, - }, &genclient.API{ + }, &api.API{ Name: "test-only-name", PackageName: "google.cloud.service.v3", }) - rustPackageNameImpl(t, "gcp-sdk-service-v3", &genclient.CodecOptions{}, &genclient.API{ + rustPackageNameImpl(t, "gcp-sdk-service-v3", &genclient.CodecOptions{}, &api.API{ Name: "test-only-name", PackageName: "google.cloud.service.v3", }) - rustPackageNameImpl(t, "gcp-sdk-type", &genclient.CodecOptions{}, &genclient.API{ + rustPackageNameImpl(t, "gcp-sdk-type", &genclient.CodecOptions{}, &api.API{ Name: "type", PackageName: "", }) } -func rustPackageNameImpl(t *testing.T, want string, copts *genclient.CodecOptions, api *genclient.API) { +func rustPackageNameImpl(t *testing.T, want string, copts *genclient.CodecOptions, api *api.API) { t.Helper() codec, err := NewRustCodec(copts) if err != nil { @@ -178,9 +179,9 @@ func checkRustPackages(t *testing.T, got *RustCodec, want *RustCodec) { func TestRust_Validate(t *testing.T) { api := newTestAPI( - []*genclient.Message{{Name: "m1", Package: "p1"}}, - []*genclient.Enum{{Name: "e1", Package: "p1"}}, - []*genclient.Service{{Name: "s1", Package: "p1"}}) + []*api.Message{{Name: "m1", Package: "p1"}}, + []*api.Enum{{Name: "e1", Package: "p1"}}, + []*api.Service{{Name: "s1", Package: "p1"}}) c := &RustCodec{} if err := c.Validate(api); err != nil { t.Errorf("unexpected error in API validation %q", err) @@ -191,36 +192,36 @@ func TestRust_Validate(t *testing.T) { } func TestRust_ValidateMessageMismatch(t *testing.T) { - api := newTestAPI( - []*genclient.Message{{Name: "m1", Package: "p1"}, {Name: "m2", Package: "p2"}}, - []*genclient.Enum{{Name: "e1", Package: "p1"}}, - []*genclient.Service{{Name: "s1", Package: "p1"}}) + test := newTestAPI( + []*api.Message{{Name: "m1", Package: "p1"}, {Name: "m2", Package: "p2"}}, + []*api.Enum{{Name: "e1", Package: "p1"}}, + []*api.Service{{Name: "s1", Package: "p1"}}) c := &RustCodec{} - if err := c.Validate(api); err == nil { + if err := c.Validate(test); err == nil { t.Errorf("expected an error in API validation got=%s", c.SourceSpecificationPackageName) } - api = newTestAPI( - []*genclient.Message{{Name: "m1", Package: "p1"}}, - []*genclient.Enum{{Name: "e1", Package: "p1"}, {Name: "e2", Package: "p2"}}, - []*genclient.Service{{Name: "s1", Package: "p1"}}) + test = newTestAPI( + []*api.Message{{Name: "m1", Package: "p1"}}, + []*api.Enum{{Name: "e1", Package: "p1"}, {Name: "e2", Package: "p2"}}, + []*api.Service{{Name: "s1", Package: "p1"}}) c = &RustCodec{} - if err := c.Validate(api); err == nil { + if err := c.Validate(test); err == nil { t.Errorf("expected an error in API validation got=%s", c.SourceSpecificationPackageName) } - api = newTestAPI( - []*genclient.Message{{Name: "m1", Package: "p1"}}, - []*genclient.Enum{{Name: "e1", Package: "p1"}}, - []*genclient.Service{{Name: "s1", Package: "p1"}, {Name: "s2", Package: "p2"}}) + test = newTestAPI( + []*api.Message{{Name: "m1", Package: "p1"}}, + []*api.Enum{{Name: "e1", Package: "p1"}}, + []*api.Service{{Name: "s1", Package: "p1"}, {Name: "s2", Package: "p2"}}) c = &RustCodec{} - if err := c.Validate(api); err == nil { + if err := c.Validate(test); err == nil { t.Errorf("expected an error in API validation got=%s", c.SourceSpecificationPackageName) } } func TestWellKnownTypesExist(t *testing.T) { - api := newTestAPI([]*genclient.Message{}, []*genclient.Enum{}, []*genclient.Service{}) + api := newTestAPI([]*api.Message{}, []*api.Enum{}, []*api.Service{}) c := &RustCodec{} c.LoadWellKnownTypes(api.State) for _, name := range []string{"Any", "Duration", "Empty", "FieldMask", "Timestamp"} { @@ -231,7 +232,7 @@ func TestWellKnownTypesExist(t *testing.T) { } func TestRust_WellKnownTypesAsMethod(t *testing.T) { - api := newTestAPI([]*genclient.Message{}, []*genclient.Enum{}, []*genclient.Service{}) + api := newTestAPI([]*api.Message{}, []*api.Enum{}, []*api.Service{}) c := createRustCodec() c.LoadWellKnownTypes(api.State) @@ -243,16 +244,16 @@ func TestRust_WellKnownTypesAsMethod(t *testing.T) { } func TestRust_MethodInOut(t *testing.T) { - message := &genclient.Message{ + message := &api.Message{ Name: "Target", ID: "..Target", } - nested := &genclient.Message{ + nested := &api.Message{ Name: "Nested", ID: "..Target.Nested", Parent: message, } - api := newTestAPI([]*genclient.Message{message, nested}, []*genclient.Enum{}, []*genclient.Service{}) + api := newTestAPI([]*api.Message{message, nested}, []*api.Enum{}, []*api.Service{}) c := createRustCodec() c.LoadWellKnownTypes(api.State) @@ -270,28 +271,28 @@ func TestRust_MethodInOut(t *testing.T) { } func TestRust_FieldAttributes(t *testing.T) { - message := &genclient.Message{ + message := &api.Message{ Name: "Fake", ID: "..Fake", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "f_int64", JSONName: "fInt64", - Typez: genclient.INT64_TYPE, + Typez: api.INT64_TYPE, Optional: false, Repeated: false, }, { Name: "f_int64_optional", JSONName: "fInt64Optional", - Typez: genclient.INT64_TYPE, + Typez: api.INT64_TYPE, Optional: true, Repeated: false, }, { Name: "f_int64_repeated", JSONName: "fInt64Repeated", - Typez: genclient.INT64_TYPE, + Typez: api.INT64_TYPE, Optional: false, Repeated: true, }, @@ -299,21 +300,21 @@ func TestRust_FieldAttributes(t *testing.T) { { Name: "f_bytes", JSONName: "fBytes", - Typez: genclient.BYTES_TYPE, + Typez: api.BYTES_TYPE, Optional: false, Repeated: false, }, { Name: "f_bytes_optional", JSONName: "fBytesOptional", - Typez: genclient.BYTES_TYPE, + Typez: api.BYTES_TYPE, Optional: true, Repeated: false, }, { Name: "f_bytes_repeated", JSONName: "fBytesRepeated", - Typez: genclient.BYTES_TYPE, + Typez: api.BYTES_TYPE, Optional: false, Repeated: true, }, @@ -321,27 +322,27 @@ func TestRust_FieldAttributes(t *testing.T) { { Name: "f_string", JSONName: "fString", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, Optional: false, Repeated: false, }, { Name: "f_string_optional", JSONName: "fStringOptional", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, Optional: true, Repeated: false, }, { Name: "f_string_repeated", JSONName: "fStringRepeated", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, Optional: false, Repeated: true, }, }, } - api := newTestAPI([]*genclient.Message{message}, []*genclient.Enum{}, []*genclient.Service{}) + api := newTestAPI([]*api.Message{message}, []*api.Enum{}, []*api.Service{}) expectedAttributes := map[string]string{ "f_int64": `#[serde_as(as = "serde_with::DisplayFromStr")]`, @@ -371,80 +372,80 @@ func TestRust_FieldAttributes(t *testing.T) { } func TestRust_MapFieldAttributes(t *testing.T) { - target := &genclient.Message{ + target := &api.Message{ Name: "Target", ID: "..Target", } - map1 := &genclient.Message{ + map1 := &api.Message{ Name: "$map", ID: "$map", IsMap: true, - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "key", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, }, { Name: "value", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, }, }, } - map2 := &genclient.Message{ + map2 := &api.Message{ Name: "$map", ID: "$map", IsMap: true, - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "key", JSONName: "key", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, }, { Name: "value", JSONName: "value", - Typez: genclient.INT64_TYPE, + Typez: api.INT64_TYPE, }, }, } - map3 := &genclient.Message{ + map3 := &api.Message{ Name: "$map", ID: "$map", IsMap: true, - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "key", - Typez: genclient.INT64_TYPE, + Typez: api.INT64_TYPE, }, { Name: "value", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, }, }, } - map4 := &genclient.Message{ + map4 := &api.Message{ Name: "$map", ID: "$map", IsMap: true, - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "key", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, }, { Name: "value", - Typez: genclient.BYTES_TYPE, + Typez: api.BYTES_TYPE, }, }, } - message := &genclient.Message{ + message := &api.Message{ Name: "Fake", ID: "..Fake", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "target", JSONName: "target", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: target.ID, Optional: true, Repeated: false, @@ -452,30 +453,30 @@ func TestRust_MapFieldAttributes(t *testing.T) { { Name: "map", JSONName: "map", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: map1.ID, }, { Name: "map_i64", JSONName: "mapI64", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: map2.ID, }, { Name: "map_i64_key", JSONName: "mapI64Key", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: map3.ID, }, { Name: "map_bytes", JSONName: "mapBytes", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: map4.ID, }, }, } - api := newTestAPI([]*genclient.Message{target, map1, map2, map3, map4, message}, []*genclient.Enum{}, []*genclient.Service{}) + api := newTestAPI([]*api.Message{target, map1, map2, map3, map4, message}, []*api.Enum{}, []*api.Service{}) expectedAttributes := map[string]string{ "target": ``, @@ -499,41 +500,41 @@ func TestRust_MapFieldAttributes(t *testing.T) { } func TestRust_WktFieldAttributes(t *testing.T) { - message := &genclient.Message{ + message := &api.Message{ Name: "Fake", ID: "..Fake", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "f_int64", JSONName: "fInt64", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.Int64Value", Optional: true, }, { Name: "f_uint64", JSONName: "fUint64", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.UInt64Value", Optional: true, }, { Name: "f_bytes", JSONName: "fBytes", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.BytesValue", Optional: true, }, { Name: "f_string", JSONName: "fString", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.StringValue", Optional: true, }, }, } - api := newTestAPI([]*genclient.Message{message}, []*genclient.Enum{}, []*genclient.Service{}) + api := newTestAPI([]*api.Message{message}, []*api.Enum{}, []*api.Service{}) expectedAttributes := map[string]string{ "f_int64": `#[serde_as(as = "Option")]`, @@ -556,29 +557,29 @@ func TestRust_WktFieldAttributes(t *testing.T) { } func TestRust_FieldLossyName(t *testing.T) { - message := &genclient.Message{ + message := &api.Message{ Name: "SecretPayload", ID: "..SecretPayload", Documentation: "A secret payload resource in the Secret Manager API.", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "data", JSONName: "data", Documentation: "The secret data. Must be no larger than 64KiB.", - Typez: genclient.BYTES_TYPE, + Typez: api.BYTES_TYPE, TypezID: "bytes", }, { Name: "dataCrc32c", JSONName: "dataCrc32c", Documentation: "Optional. If specified, SecretManagerService will verify the integrity of the received data.", - Typez: genclient.INT64_TYPE, + Typez: api.INT64_TYPE, TypezID: "int64", Optional: true, }, }, } - api := newTestAPI([]*genclient.Message{message}, []*genclient.Enum{}, []*genclient.Service{}) + api := newTestAPI([]*api.Message{message}, []*api.Enum{}, []*api.Service{}) expectedAttributes := map[string]string{ "data": `#[serde_as(as = "serde_with::base64::Base64")]`, @@ -599,34 +600,34 @@ func TestRust_FieldLossyName(t *testing.T) { } func TestRust_SyntheticField(t *testing.T) { - message := &genclient.Message{ + message := &api.Message{ Name: "Unused", ID: "..Unused", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "updateMask", JSONName: "updateMask", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.FieldMask", Optional: true, }, { Name: "project", JSONName: "project", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: "string", Synthetic: true, }, { Name: "data_crc32c", JSONName: "dataCrc32c", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: "string", Synthetic: true, }, }, } - api := newTestAPI([]*genclient.Message{message}, []*genclient.Enum{}, []*genclient.Service{}) + api := newTestAPI([]*api.Message{message}, []*api.Enum{}, []*api.Service{}) expectedAttributes := map[string]string{ "updateMask": ``, @@ -648,63 +649,63 @@ func TestRust_SyntheticField(t *testing.T) { } func TestRust_FieldType(t *testing.T) { - target := &genclient.Message{ + target := &api.Message{ Name: "Target", ID: "..Target", } - message := &genclient.Message{ + message := &api.Message{ Name: "Fake", ID: "..Fake", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "f_int32", - Typez: genclient.INT32_TYPE, + Typez: api.INT32_TYPE, Optional: false, Repeated: false, }, { Name: "f_int32_optional", - Typez: genclient.INT32_TYPE, + Typez: api.INT32_TYPE, Optional: true, Repeated: false, }, { Name: "f_int32_repeated", - Typez: genclient.INT32_TYPE, + Typez: api.INT32_TYPE, Optional: false, Repeated: true, }, { Name: "f_msg", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: "..Target", Optional: true, Repeated: false, }, { Name: "f_msg_repeated", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: "..Target", Optional: false, Repeated: true, }, { Name: "f_timestamp", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.Timestamp", Optional: true, Repeated: false, }, { Name: "f_timestamp_repeated", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.Timestamp", Optional: false, Repeated: true, }, }, } - api := newTestAPI([]*genclient.Message{target, message}, []*genclient.Enum{}, []*genclient.Service{}) + api := newTestAPI([]*api.Message{target, message}, []*api.Enum{}, []*api.Service{}) expectedTypes := map[string]string{ "f_int32": "i32", @@ -730,39 +731,39 @@ func TestRust_FieldType(t *testing.T) { } func TestRust_QueryParams(t *testing.T) { - options := &genclient.Message{ + options := &api.Message{ Name: "Options", ID: "..Options", - Fields: []*genclient.Field{}, + Fields: []*api.Field{}, } - optionsField := &genclient.Field{ + optionsField := &api.Field{ Name: "options_field", JSONName: "optionsField", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: options.ID, } - anotherField := &genclient.Field{ + anotherField := &api.Field{ Name: "another_field", JSONName: "anotherField", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: options.ID, } - request := &genclient.Message{ + request := &api.Message{ Name: "TestRequest", ID: "..TestRequest", - Fields: []*genclient.Field{ + Fields: []*api.Field{ optionsField, anotherField, { Name: "unused", }, }, } - method := &genclient.Method{ + method := &api.Method{ Name: "Test", ID: "..TestService.Test", InputTypeID: request.ID, OutputTypeID: ".google.protobuf.Empty", - PathInfo: &genclient.PathInfo{ + PathInfo: &api.PathInfo{ Verb: "GET", QueryParameters: map[string]bool{ "options_field": true, @@ -770,54 +771,54 @@ func TestRust_QueryParams(t *testing.T) { }, }, } - api := newTestAPI( - []*genclient.Message{options, request}, - []*genclient.Enum{}, - []*genclient.Service{ + test := newTestAPI( + []*api.Message{options, request}, + []*api.Enum{}, + []*api.Service{ { Name: "TestService", ID: "..TestService", - Methods: []*genclient.Method{method}, + Methods: []*api.Method{method}, }, }) c := createRustCodec() - c.LoadWellKnownTypes(api.State) + c.LoadWellKnownTypes(test.State) - got := c.QueryParams(method, api.State) - want := []*genclient.Field{optionsField, anotherField} - less := func(a, b *genclient.Field) bool { return a.Name < b.Name } + got := c.QueryParams(method, test.State) + want := []*api.Field{optionsField, anotherField} + less := func(a, b *api.Field) bool { return a.Name < b.Name } if diff := cmp.Diff(want, got, cmpopts.SortSlices(less)); diff != "" { t.Errorf("mismatched query parameters (-want, +got):\n%s", diff) } } func TestRust_AsQueryParameter(t *testing.T) { - options := &genclient.Message{ + options := &api.Message{ Name: "Options", ID: "..Options", - Fields: []*genclient.Field{}, + Fields: []*api.Field{}, } - optionsField := &genclient.Field{ + optionsField := &api.Field{ Name: "options_field", JSONName: "optionsField", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: options.ID, } - anotherField := &genclient.Field{ + anotherField := &api.Field{ Name: "another_field", JSONName: "anotherField", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: options.ID, } - request := &genclient.Message{ + request := &api.Message{ Name: "TestRequest", ID: "..TestRequest", - Fields: []*genclient.Field{optionsField, anotherField}, + Fields: []*api.Field{optionsField, anotherField}, } api := newTestAPI( - []*genclient.Message{options, request}, - []*genclient.Enum{}, - []*genclient.Service{}) + []*api.Message{options, request}, + []*api.Enum{}, + []*api.Service{}) c := createRustCodec() c.LoadWellKnownTypes(api.State) @@ -949,26 +950,26 @@ func TestRust_FormatDocCommentsBullets(t *testing.T) { } func TestRust_MessageNames(t *testing.T) { - message := &genclient.Message{ + message := &api.Message{ Name: "Replication", ID: "..Replication", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "automatic", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: "..Automatic", Optional: true, Repeated: false, }, }, } - nested := &genclient.Message{ + nested := &api.Message{ Name: "Automatic", ID: "..Replication.Automatic", Parent: message, } - api := newTestAPI([]*genclient.Message{message, nested}, []*genclient.Enum{}, []*genclient.Service{}) + api := newTestAPI([]*api.Message{message, nested}, []*api.Enum{}, []*api.Service{}) c := createRustCodec() if got := c.MessageName(message, api.State); got != "Replication" { @@ -987,26 +988,26 @@ func TestRust_MessageNames(t *testing.T) { } func TestRust_EnumNames(t *testing.T) { - message := &genclient.Message{ + message := &api.Message{ Name: "SecretVersion", ID: "..SecretVersion", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "automatic", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: "..Automatic", Optional: true, Repeated: false, }, }, } - nested := &genclient.Enum{ + nested := &api.Enum{ Name: "State", ID: "..SecretVersion.State", Parent: message, } - api := newTestAPI([]*genclient.Message{message}, []*genclient.Enum{nested}, []*genclient.Service{}) + api := newTestAPI([]*api.Message{message}, []*api.Enum{nested}, []*api.Service{}) c := createRustCodec() if got := c.EnumName(nested, api.State); got != "State" { diff --git a/generator/internal/parser/annotations.go b/generator/internal/parser/annotations.go index 41cd93e34..654f661cc 100644 --- a/generator/internal/parser/annotations.go +++ b/generator/internal/parser/annotations.go @@ -19,19 +19,19 @@ import ( "log/slog" "strings" - "github.com/googleapis/google-cloud-rust/generator/internal/genclient" + "github.com/googleapis/google-cloud-rust/generator/internal/api" "google.golang.org/genproto/googleapis/api/annotations" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/descriptorpb" ) -func parsePathInfo(m *descriptorpb.MethodDescriptorProto, state *genclient.APIState) (*genclient.PathInfo, error) { +func parsePathInfo(m *descriptorpb.MethodDescriptorProto, state *api.APIState) (*api.PathInfo, error) { eHTTP := proto.GetExtension(m.GetOptions(), annotations.E_Http) httpRule := eHTTP.(*annotations.HttpRule) return processRule(httpRule, state, m.GetInputType()) } -func processRule(httpRule *annotations.HttpRule, state *genclient.APIState, mID string) (*genclient.PathInfo, error) { +func processRule(httpRule *annotations.HttpRule, state *api.APIState, mID string) (*api.PathInfo, error) { var verb string var rawPath string switch httpRule.GetPattern().(type) { @@ -59,7 +59,7 @@ func processRule(httpRule *annotations.HttpRule, state *genclient.APIState, mID return nil, err } - return &genclient.PathInfo{ + return &api.PathInfo{ Verb: verb, PathTemplate: pathTemplate, QueryParameters: queryParameters, @@ -67,7 +67,7 @@ func processRule(httpRule *annotations.HttpRule, state *genclient.APIState, mID }, nil } -func queryParameters(msgID string, pathTemplate []genclient.PathSegment, body string, state *genclient.APIState) (map[string]bool, error) { +func queryParameters(msgID string, pathTemplate []api.PathSegment, body string, state *api.APIState) (map[string]bool, error) { msg, ok := state.MessageByID[msgID] if !ok { return nil, fmt.Errorf("unable to lookup type %s", msgID) @@ -92,19 +92,19 @@ func queryParameters(msgID string, pathTemplate []genclient.PathSegment, body st return params, nil } -func parseRawPath(rawPath string) []genclient.PathSegment { +func parseRawPath(rawPath string) []api.PathSegment { // TODO(#121) - use a proper parser for the template syntax - template := genclient.HTTPPathVarRegex.ReplaceAllStringFunc(rawPath, func(s string) string { + template := api.HTTPPathVarRegex.ReplaceAllStringFunc(rawPath, func(s string) string { members := strings.Split(s, "=") if len(members) == 1 { return members[0] } return members[0] + "}" }) - segments := []genclient.PathSegment{} + segments := []api.PathSegment{} for idx, component := range strings.Split(template, ":") { if idx != 0 { - segments = append(segments, genclient.PathSegment{Verb: &component}) + segments = append(segments, api.PathSegment{Verb: &component}) continue } for _, element := range strings.Split(component, "/") { @@ -113,10 +113,10 @@ func parseRawPath(rawPath string) []genclient.PathSegment { } if strings.HasPrefix(element, "{") && strings.HasSuffix(element, "}") { element = element[1 : len(element)-1] - segments = append(segments, genclient.PathSegment{FieldPath: &element}) + segments = append(segments, api.PathSegment{FieldPath: &element}) continue } - segments = append(segments, genclient.PathSegment{Literal: &element}) + segments = append(segments, api.PathSegment{Literal: &element}) } } return segments diff --git a/generator/internal/parser/mixin.go b/generator/internal/parser/mixin.go index e344d32aa..024c4f516 100644 --- a/generator/internal/parser/mixin.go +++ b/generator/internal/parser/mixin.go @@ -21,7 +21,7 @@ import ( "cloud.google.com/go/iam/apiv1/iampb" "cloud.google.com/go/longrunning/autogen/longrunningpb" - "github.com/googleapis/google-cloud-rust/generator/internal/genclient" + "github.com/googleapis/google-cloud-rust/generator/internal/api" "google.golang.org/genproto/googleapis/api/serviceconfig" "google.golang.org/genproto/googleapis/cloud/location" "google.golang.org/protobuf/reflect/protodesc" @@ -78,7 +78,7 @@ func loadMixinMethods(serviceConfig *serviceconfig.Service) mixinMethods { // updateMixinState modifies mixin method definitions based on configuration in // the service yaml. -func updateMixinState(serviceConfig *serviceconfig.Service, api *genclient.API) { +func updateMixinState(serviceConfig *serviceconfig.Service, api *api.API) { // Overwrite the google.api.http annotations with bindings from the Service config. for _, rule := range serviceConfig.GetHttp().GetRules() { selector := rule.GetSelector() diff --git a/generator/internal/parser/openapi.go b/generator/internal/parser/openapi.go index 3691279e1..47c3533dd 100644 --- a/generator/internal/parser/openapi.go +++ b/generator/internal/parser/openapi.go @@ -22,6 +22,7 @@ import ( "os" "strings" + "github.com/googleapis/google-cloud-rust/generator/internal/api" "github.com/googleapis/google-cloud-rust/generator/internal/genclient" "github.com/pb33f/libopenapi" "github.com/pb33f/libopenapi/datamodel/high/base" @@ -30,7 +31,7 @@ import ( "google.golang.org/genproto/googleapis/api/serviceconfig" ) -func ParseOpenAPI(opts genclient.ParserOptions) (*genclient.API, error) { +func ParseOpenAPI(opts genclient.ParserOptions) (*api.API, error) { contents, err := os.ReadFile(opts.Source) if err != nil { return nil, err @@ -47,7 +48,6 @@ func ParseOpenAPI(opts genclient.ParserOptions) (*genclient.API, error) { } serviceConfig = cfg } - // Translates OpenAPI specification into a [genclient.GenerateRequest]. return makeAPIForOpenAPI(serviceConfig, model) } @@ -63,24 +63,24 @@ func createDocModel(contents []byte) (*libopenapi.DocumentModel[v3.Document], er return docModel, nil } -func makeAPIForOpenAPI(serviceConfig *serviceconfig.Service, model *libopenapi.DocumentModel[v3.Document]) (*genclient.API, error) { - api := &genclient.API{ +func makeAPIForOpenAPI(serviceConfig *serviceconfig.Service, model *libopenapi.DocumentModel[v3.Document]) (*api.API, error) { + a := &api.API{ Name: "", Title: model.Model.Info.Title, Description: model.Model.Info.Description, - Messages: make([]*genclient.Message, 0), - State: &genclient.APIState{ - ServiceByID: make(map[string]*genclient.Service), - MethodByID: make(map[string]*genclient.Method), - MessageByID: make(map[string]*genclient.Message), - EnumByID: make(map[string]*genclient.Enum), + Messages: make([]*api.Message, 0), + State: &api.APIState{ + ServiceByID: make(map[string]*api.Service), + MethodByID: make(map[string]*api.Method), + MessageByID: make(map[string]*api.Message), + EnumByID: make(map[string]*api.Enum), }, } if serviceConfig != nil { - api.Name = strings.TrimSuffix(serviceConfig.Name, ".googleapis.com") - api.Title = serviceConfig.Title - api.Description = serviceConfig.Documentation.Summary + a.Name = strings.TrimSuffix(serviceConfig.Name, ".googleapis.com") + a.Title = serviceConfig.Title + a.Description = serviceConfig.Documentation.Summary } // OpenAPI does not define a service name. The service config may provide @@ -103,11 +103,11 @@ func makeAPIForOpenAPI(serviceConfig *serviceconfig.Service, model *libopenapi.D if err != nil { return nil, err } - fields, err := makeMessageFields(api.State, packageName, name, schema) + fields, err := makeMessageFields(a.State, packageName, name, schema) if err != nil { return nil, err } - message := &genclient.Message{ + message := &api.Message{ Name: name, ID: id, Package: packageName, @@ -115,18 +115,18 @@ func makeAPIForOpenAPI(serviceConfig *serviceconfig.Service, model *libopenapi.D Fields: fields, } - api.Messages = append(api.Messages, message) - api.State.MessageByID[id] = message + a.Messages = append(a.Messages, message) + a.State.MessageByID[id] = message } - err := makeServices(api, model, packageName, serviceName) + err := makeServices(a, model, packageName, serviceName) if err != nil { return nil, err } - return api, nil + return a, nil } -func makeServices(api *genclient.API, model *libopenapi.DocumentModel[v3.Document], packageName, serviceName string) error { +func makeServices(a *api.API, model *libopenapi.DocumentModel[v3.Document], packageName, serviceName string) error { // It is hard to imagine an OpenAPI specification without at least some // RPCs, but we can simplify the tests if we support specifications without // paths or without any useful methods in the paths. @@ -134,23 +134,23 @@ func makeServices(api *genclient.API, model *libopenapi.DocumentModel[v3.Documen return nil } sID := fmt.Sprintf(".%s.%s", packageName, serviceName) - methods, err := makeMethods(api, model, packageName, sID) + methods, err := makeMethods(a, model, packageName, sID) if err != nil { return err } if len(methods) == 0 { return nil } - service := &genclient.Service{ + service := &api.Service{ Name: serviceName, ID: fmt.Sprintf(".%s.%s", packageName, serviceName), Package: packageName, - Documentation: api.Description, + Documentation: a.Description, DefaultHost: defaultHost(model), Methods: methods, } - api.Services = append(api.Services, service) - api.State.ServiceByID[service.ID] = service + a.Services = append(a.Services, service) + a.State.ServiceByID[service.ID] = service return nil } @@ -168,8 +168,8 @@ func defaultHost(model *libopenapi.DocumentModel[v3.Document]) string { return strings.TrimPrefix(defaultHost, "https://") } -func makeMethods(api *genclient.API, model *libopenapi.DocumentModel[v3.Document], packageName, serviceID string) ([]*genclient.Method, error) { - methods := []*genclient.Method{} +func makeMethods(a *api.API, model *libopenapi.DocumentModel[v3.Document], packageName, serviceID string) ([]*api.Method, error) { + var methods []*api.Method if model.Model.Paths == nil { return methods, nil } @@ -194,22 +194,22 @@ func makeMethods(api *genclient.API, model *libopenapi.DocumentModel[v3.Document if op.Operation == nil { continue } - requestMessage, bodyFieldPath, err := makeRequestMessage(api, op.Operation, packageName, pattern) + requestMessage, bodyFieldPath, err := makeRequestMessage(a, op.Operation, packageName, pattern) if err != nil { return nil, err } - responseMessage, err := makeResponseMessage(api, op.Operation, packageName) + responseMessage, err := makeResponseMessage(a, op.Operation, packageName) if err != nil { return nil, err } - pathInfo := &genclient.PathInfo{ + pathInfo := &api.PathInfo{ Verb: op.Verb, PathTemplate: pathTemplate, QueryParameters: makeQueryParameters(op.Operation), BodyFieldPath: bodyFieldPath, } mID := fmt.Sprintf("%s.%s", serviceID, op.Operation.OperationId) - m := &genclient.Method{ + m := &api.Method{ Name: op.Operation.OperationId, ID: mID, Documentation: op.Operation.Description, @@ -217,18 +217,18 @@ func makeMethods(api *genclient.API, model *libopenapi.DocumentModel[v3.Document OutputTypeID: responseMessage.ID, PathInfo: pathInfo, } - api.State.MethodByID[m.ID] = m + a.State.MethodByID[m.ID] = m methods = append(methods, m) } } return methods, nil } -func makePathTemplate(template string) []genclient.PathSegment { - segments := []genclient.PathSegment{} +func makePathTemplate(template string) []api.PathSegment { + segments := []api.PathSegment{} for idx, component := range strings.Split(template, ":") { if idx != 0 { - segments = append(segments, genclient.PathSegment{Verb: &component}) + segments = append(segments, api.PathSegment{Verb: &component}) continue } for _, element := range strings.Split(component, "/") { @@ -237,10 +237,10 @@ func makePathTemplate(template string) []genclient.PathSegment { } if strings.HasPrefix(element, "{") && strings.HasSuffix(element, "}") { element = element[1 : len(element)-1] - segments = append(segments, genclient.PathSegment{FieldPath: &element}) + segments = append(segments, api.PathSegment{FieldPath: &element}) continue } - segments = append(segments, genclient.PathSegment{Literal: &element}) + segments = append(segments, api.PathSegment{Literal: &element}) } } return segments @@ -248,10 +248,10 @@ func makePathTemplate(template string) []genclient.PathSegment { // Creates (if needed) the request message for `operation`. Returns the message // and the body field path (if any) for the request. -func makeRequestMessage(api *genclient.API, operation *v3.Operation, packageName, template string) (*genclient.Message, string, error) { +func makeRequestMessage(a *api.API, operation *v3.Operation, packageName, template string) (*api.Message, string, error) { messageName := fmt.Sprintf("%sRequest", operation.OperationId) id := fmt.Sprintf(".%s.%s", packageName, messageName) - message := &genclient.Message{ + message := &api.Message{ Name: messageName, ID: id, Package: packageName, @@ -265,7 +265,7 @@ func makeRequestMessage(api *genclient.API, operation *v3.Operation, packageName return nil, "", err } bid := fmt.Sprintf(".%s.%s", packageName, strings.TrimPrefix(reference, "#/components/schemas/")) - msg, ok := api.State.MessageByID[bid] + msg, ok := a.State.MessageByID[bid] if !ok { return nil, "", fmt.Errorf("cannot find referenced type (%s) in API messages", reference) } @@ -285,11 +285,11 @@ func makeRequestMessage(api *genclient.API, operation *v3.Operation, packageName // couple of different names. inserted := false for _, name := range []string{"requestBody", "openapiRequestBody"} { - field := &genclient.Field{ + field := &api.Field{ Name: name, JSONName: name, Documentation: "The request body.", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: bid, Optional: true, } @@ -304,13 +304,13 @@ func makeRequestMessage(api *genclient.API, operation *v3.Operation, packageName return nil, "", fmt.Errorf("cannot insert the request body to message %s", message.Name) } // We need to create the message. - api.Messages = append(api.Messages, message) - api.State.MessageByID[message.ID] = message + a.Messages = append(a.Messages, message) + a.State.MessageByID[message.ID] = message } } else { // The message is new - api.Messages = append(api.Messages, message) - api.State.MessageByID[message.ID] = message + a.Messages = append(a.Messages, message) + a.State.MessageByID[message.ID] = message } for _, p := range operation.Parameters { @@ -331,7 +331,7 @@ func makeRequestMessage(api *genclient.API, operation *v3.Operation, packageName "\n"+ "The full target path will be in the form `%s`.", p.Name, template) } - field := &genclient.Field{ + field := &api.Field{ Name: p.Name, JSONName: p.Name, // OpenAPI fields are already camelCase Documentation: documentation, @@ -345,7 +345,7 @@ func makeRequestMessage(api *genclient.API, operation *v3.Operation, packageName return message, bodyFieldPath, nil } -func addFieldIfNew(message *genclient.Message, field *genclient.Field) bool { +func addFieldIfNew(message *api.Message, field *api.Field) bool { for _, f := range message.Fields { if f.Name == field.Name { // If the exact same field exists, treat that as a success. @@ -356,7 +356,7 @@ func addFieldIfNew(message *genclient.Message, field *genclient.Field) bool { return true } -func makeResponseMessage(api *genclient.API, operation *v3.Operation, packageName string) (*genclient.Message, error) { +func makeResponseMessage(api *api.API, operation *v3.Operation, packageName string) (*api.Message, error) { if operation.Responses == nil { return nil, fmt.Errorf("missing Responses in specification for operation %s", operation.OperationId) } @@ -396,8 +396,8 @@ func makeQueryParameters(operation *v3.Operation) map[string]bool { return queryParameters } -func makeMessageFields(state *genclient.APIState, packageName, messageName string, message *base.Schema) ([]*genclient.Field, error) { - var fields []*genclient.Field +func makeMessageFields(state *api.APIState, packageName, messageName string, message *base.Schema) ([]*api.Field, error) { + var fields []*api.Field for name, f := range message.Properties.FromOldest() { schema, err := f.BuildSchema() if err != nil { @@ -419,7 +419,7 @@ func makeMessageFields(state *genclient.APIState, packageName, messageName strin return fields, nil } -func makeField(state *genclient.APIState, packageName, messageName, name string, optional bool, field *base.Schema) (*genclient.Field, error) { +func makeField(state *api.APIState, packageName, messageName, name string, optional bool, field *base.Schema) (*api.Field, error) { if len(field.AllOf) != 0 { // Simple object fields name an AllOf attribute, but no `Type` attribute. return makeObjectField(state, packageName, messageName, name, field) @@ -439,22 +439,22 @@ func makeField(state *genclient.APIState, packageName, messageName, name string, } } -func makeScalarField(messageName, name string, schema *base.Schema, optional bool, field *base.Schema) (*genclient.Field, error) { +func makeScalarField(messageName, name string, schema *base.Schema, optional bool, field *base.Schema) (*api.Field, error) { typez, typezID, err := scalarType(messageName, name, schema) if err != nil { return nil, err } - return &genclient.Field{ + return &api.Field{ Name: name, JSONName: name, // OpenAPI field names are always camelCase Documentation: field.Description, Typez: typez, TypezID: typezID, - Optional: optional || (typez == genclient.MESSAGE_TYPE), + Optional: optional || (typez == api.MESSAGE_TYPE), }, nil } -func makeObjectField(state *genclient.APIState, packageName, messageName, name string, field *base.Schema) (*genclient.Field, error) { +func makeObjectField(state *api.APIState, packageName, messageName, name string, field *base.Schema) (*api.Field, error) { if len(field.AllOf) != 0 { return makeObjectFieldAllOf(packageName, messageName, name, field) } @@ -468,11 +468,11 @@ func makeObjectField(state *genclient.APIState, packageName, messageName, name s if len(schema.Type) == 0 { // Untyped message fields are .google.protobuf.Any - return &genclient.Field{ + return &api.Field{ Name: name, JSONName: name, // OpenAPI field names are always camelCase Documentation: field.Description, - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.Any", Optional: true, }, nil @@ -481,11 +481,11 @@ func makeObjectField(state *genclient.APIState, packageName, messageName, name s if err != nil { return nil, err } - return &genclient.Field{ + return &api.Field{ Name: name, JSONName: name, // OpenAPI field names are always camelCase Documentation: field.Description, - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: message.ID, Optional: false, }, nil @@ -493,11 +493,11 @@ func makeObjectField(state *genclient.APIState, packageName, messageName, name s if field.Items != nil && field.Items.IsA() { proxy := field.Items.A typezID := fmt.Sprintf(".%s.%s", packageName, strings.TrimPrefix(proxy.GetReference(), "#/components/schemas/")) - return &genclient.Field{ + return &api.Field{ Name: name, JSONName: name, // OpenAPI field names are always camelCase Documentation: field.Description, - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: typezID, Optional: true, }, nil @@ -505,7 +505,7 @@ func makeObjectField(state *genclient.APIState, packageName, messageName, name s return nil, fmt.Errorf("unknown object field type for field %s.%s", messageName, name) } -func makeArrayField(state *genclient.APIState, packageName, messageName, name string, field *base.Schema) (*genclient.Field, error) { +func makeArrayField(state *api.APIState, packageName, messageName, name string, field *base.Schema) (*api.Field, error) { if !field.Items.IsA() { return nil, fmt.Errorf("cannot handle arrays without an `Items` field for %s.%s", messageName, name) } @@ -517,18 +517,18 @@ func makeArrayField(state *genclient.APIState, packageName, messageName, name st if len(schema.Type) != 1 { return nil, fmt.Errorf("the items for field %s.%s should have a single type", messageName, name) } - var result *genclient.Field + var result *api.Field switch schema.Type[0] { case "boolean", "integer", "number", "string": result, err = makeScalarField(messageName, name, schema, false, field) case "object": typezID := fmt.Sprintf(".%s.%s", packageName, strings.TrimPrefix(reference, "#/components/schemas/")) if len(typezID) > 0 { - new := &genclient.Field{ + new := &api.Field{ Name: name, JSONName: name, // OpenAPI field names are always camelCase Documentation: field.Description, - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: typezID, } result = new @@ -546,14 +546,14 @@ func makeArrayField(state *genclient.APIState, packageName, messageName, name st return result, nil } -func makeObjectFieldAllOf(packageName, messageName, name string, field *base.Schema) (*genclient.Field, error) { +func makeObjectFieldAllOf(packageName, messageName, name string, field *base.Schema) (*api.Field, error) { for _, proxy := range field.AllOf { typezID := fmt.Sprintf(".%s.%s", packageName, strings.TrimPrefix(proxy.GetReference(), "#/components/schemas/")) - return &genclient.Field{ + return &api.Field{ Name: name, JSONName: name, // OpenAPI field names are always camelCase Documentation: field.Description, - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: typezID, Optional: true, }, nil @@ -561,12 +561,12 @@ func makeObjectFieldAllOf(packageName, messageName, name string, field *base.Sch return nil, fmt.Errorf("cannot build any AllOf schema for field %s.%s", messageName, name) } -func makeMapMessage(state *genclient.APIState, messageName, name string, schema *base.Schema) (*genclient.Message, error) { +func makeMapMessage(state *api.APIState, messageName, name string, schema *base.Schema) (*api.Message, error) { value_typez, value_id, err := scalarType(messageName, name, schema) if err != nil { return nil, err } - value := &genclient.Field{ + value := &api.Field{ Name: "value", ID: value_id, Typez: value_typez, @@ -577,19 +577,19 @@ func makeMapMessage(state *genclient.APIState, messageName, name string, schema message := state.MessageByID[id] if message == nil { // The map was not found, insert the type. - key := &genclient.Field{ + key := &api.Field{ Name: "key", ID: id + ".key", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: "string", } - placeholder := &genclient.Message{ + placeholder := &api.Message{ Name: id, Documentation: id, ID: id, IsLocalToPackage: false, IsMap: true, - Fields: []*genclient.Field{key, value}, + Fields: []*api.Field{key, value}, Parent: nil, Package: "$", } @@ -599,11 +599,11 @@ func makeMapMessage(state *genclient.APIState, messageName, name string, schema return message, nil } -func scalarType(messageName, name string, schema *base.Schema) (genclient.Typez, string, error) { +func scalarType(messageName, name string, schema *base.Schema) (api.Typez, string, error) { for _, type_name := range schema.Type { switch type_name { case "boolean": - return genclient.BOOL_TYPE, "bool", nil + return api.BOOL_TYPE, "bool", nil case "integer": return scalarTypeForIntegerFormats(messageName, name, schema) case "number": @@ -615,54 +615,54 @@ func scalarType(messageName, name string, schema *base.Schema) (genclient.Typez, return 0, "", fmt.Errorf("expected a scalar type for field %s.%s", messageName, name) } -func scalarTypeForIntegerFormats(messageName, name string, schema *base.Schema) (genclient.Typez, string, error) { +func scalarTypeForIntegerFormats(messageName, name string, schema *base.Schema) (api.Typez, string, error) { switch schema.Format { case "int32": if schema.Minimum != nil && *schema.Minimum == 0 { - return genclient.UINT32_TYPE, "uint32", nil + return api.UINT32_TYPE, "uint32", nil } - return genclient.INT32_TYPE, "int32", nil + return api.INT32_TYPE, "int32", nil case "int64": if schema.Minimum != nil && *schema.Minimum == 0 { - return genclient.UINT64_TYPE, "uint64", nil + return api.UINT64_TYPE, "uint64", nil } - return genclient.INT64_TYPE, "int64", nil + return api.INT64_TYPE, "int64", nil } return 0, "", fmt.Errorf("unknown integer format (%s) for field %s.%s", schema.Format, messageName, name) } -func scalarTypeForNumberFormats(messageName, name string, schema *base.Schema) (genclient.Typez, string, error) { +func scalarTypeForNumberFormats(messageName, name string, schema *base.Schema) (api.Typez, string, error) { switch schema.Format { case "float": - return genclient.FLOAT_TYPE, "float", nil + return api.FLOAT_TYPE, "float", nil case "double": - return genclient.DOUBLE_TYPE, "double", nil + return api.DOUBLE_TYPE, "double", nil } return 0, "", fmt.Errorf("unknown number format (%s) for field %s.%s", schema.Format, messageName, name) } -func scalarTypeForStringFormats(messageName, name string, schema *base.Schema) (genclient.Typez, string, error) { +func scalarTypeForStringFormats(messageName, name string, schema *base.Schema) (api.Typez, string, error) { switch schema.Format { case "": - return genclient.STRING_TYPE, "string", nil + return api.STRING_TYPE, "string", nil case "byte": - return genclient.BYTES_TYPE, "bytes", nil + return api.BYTES_TYPE, "bytes", nil case "int32": if schema.Minimum != nil && *schema.Minimum == 0 { - return genclient.UINT32_TYPE, "uint32", nil + return api.UINT32_TYPE, "uint32", nil } - return genclient.INT32_TYPE, "int32", nil + return api.INT32_TYPE, "int32", nil case "int64": if schema.Minimum != nil && *schema.Minimum == 0 { - return genclient.UINT64_TYPE, "uint64", nil + return api.UINT64_TYPE, "uint64", nil } - return genclient.INT64_TYPE, "int64", nil + return api.INT64_TYPE, "int64", nil case "google-duration": - return genclient.MESSAGE_TYPE, ".google.protobuf.Duration", nil + return api.MESSAGE_TYPE, ".google.protobuf.Duration", nil case "date-time": - return genclient.MESSAGE_TYPE, ".google.protobuf.Timestamp", nil + return api.MESSAGE_TYPE, ".google.protobuf.Timestamp", nil case "google-fieldmask": - return genclient.MESSAGE_TYPE, ".google.protobuf.FieldMask", nil + return api.MESSAGE_TYPE, ".google.protobuf.FieldMask", nil } return 0, "", fmt.Errorf("unknown string format (%s) for field %s.%s", schema.Format, messageName, name) } diff --git a/generator/internal/parser/openapi_test.go b/generator/internal/parser/openapi_test.go index e70305d4b..b4b45c4eb 100644 --- a/generator/internal/parser/openapi_test.go +++ b/generator/internal/parser/openapi_test.go @@ -20,7 +20,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/googleapis/google-cloud-rust/generator/internal/genclient" + "github.com/googleapis/google-cloud-rust/generator/internal/api" ) func TestOpenAPI_AllOf(t *testing.T) { @@ -57,26 +57,26 @@ func TestOpenAPI_AllOf(t *testing.T) { if err != nil { t.Fatal(err) } - api, err := makeAPIForOpenAPI(nil, model) + test, err := makeAPIForOpenAPI(nil, model) if err != nil { t.Fatalf("Error in makeAPI() %q", err) } - message := api.State.MessageByID["..Automatic"] + message := test.State.MessageByID["..Automatic"] if message == nil { t.Errorf("missing message in MessageByID index") return } - checkMessage(t, *message, genclient.Message{ + checkMessage(t, *message, api.Message{ Name: "Automatic", ID: "..Automatic", Documentation: "A replication policy that replicates the Secret payload without any restrictions.", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "customerManagedEncryption", JSONName: "customerManagedEncryption", Documentation: "Optional. The customer-managed encryption configuration of the Secret.", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: "..CustomerManagedEncryption", Optional: true, }, @@ -121,106 +121,106 @@ func TestOpenAPI_BasicTypes(t *testing.T) { t.Fatal(err) } - api, err := makeAPIForOpenAPI(nil, model) + test, err := makeAPIForOpenAPI(nil, model) if err != nil { t.Fatalf("Error in makeAPI() %q", err) } - message := api.State.MessageByID["..Fake"] + message := test.State.MessageByID["..Fake"] if message == nil { t.Errorf("missing message in MessageByID index") return } - checkMessage(t, *message, genclient.Message{ + checkMessage(t, *message, api.Message{ Name: "Fake", ID: "..Fake", Documentation: "A test message.", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "fBool", JSONName: "fBool", - Typez: genclient.BOOL_TYPE, + Typez: api.BOOL_TYPE, TypezID: "bool", }, { Name: "fInt64", JSONName: "fInt64", - Typez: genclient.INT64_TYPE, + Typez: api.INT64_TYPE, TypezID: "int64", }, { Name: "fInt32", JSONName: "fInt32", - Typez: genclient.INT32_TYPE, + Typez: api.INT32_TYPE, TypezID: "int32", }, { Name: "fUInt32", JSONName: "fUInt32", - Typez: genclient.UINT32_TYPE, + Typez: api.UINT32_TYPE, TypezID: "uint32", }, { Name: "fFloat", JSONName: "fFloat", - Typez: genclient.FLOAT_TYPE, + Typez: api.FLOAT_TYPE, TypezID: "float", }, { Name: "fDouble", JSONName: "fDouble", - Typez: genclient.DOUBLE_TYPE, + Typez: api.DOUBLE_TYPE, TypezID: "double", }, { Name: "fString", JSONName: "fString", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: "string", }, { Name: "fOptional", JSONName: "fOptional", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: "string", Optional: true}, { Name: "fSInt64", JSONName: "fSInt64", - Typez: genclient.INT64_TYPE, + Typez: api.INT64_TYPE, TypezID: "int64", }, { Name: "fSUInt64", JSONName: "fSUInt64", - Typez: genclient.UINT64_TYPE, + Typez: api.UINT64_TYPE, TypezID: "uint64", }, { Name: "fDuration", JSONName: "fDuration", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.Duration", Optional: true, }, { Name: "fTimestamp", JSONName: "fTimestamp", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.Timestamp", Optional: true, }, { Name: "fFieldMask", JSONName: "fFieldMask", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.FieldMask", Optional: true, }, { Name: "fBytes", JSONName: "fBytes", - Typez: genclient.BYTES_TYPE, + Typez: api.BYTES_TYPE, TypezID: "bytes", }, }, @@ -253,89 +253,89 @@ func TestOpenAPI_ArrayTypes(t *testing.T) { if err != nil { t.Fatal(err) } - api, err := makeAPIForOpenAPI(nil, model) + test, err := makeAPIForOpenAPI(nil, model) if err != nil { t.Fatalf("Error in makeAPI() %q", err) } - message := api.State.MessageByID["..Fake"] + message := test.State.MessageByID["..Fake"] if message == nil { t.Errorf("missing message in MessageByID index") return } - checkMessage(t, *message, genclient.Message{ + checkMessage(t, *message, api.Message{ Name: "Fake", ID: "..Fake", Documentation: "A test message.", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Repeated: true, Name: "fBool", JSONName: "fBool", - Typez: genclient.BOOL_TYPE, + Typez: api.BOOL_TYPE, TypezID: "bool"}, { Repeated: true, Name: "fInt64", JSONName: "fInt64", - Typez: genclient.INT64_TYPE, + Typez: api.INT64_TYPE, TypezID: "int64"}, { Repeated: true, Name: "fInt32", JSONName: "fInt32", - Typez: genclient.INT32_TYPE, + Typez: api.INT32_TYPE, TypezID: "int32"}, { Repeated: true, Name: "fUInt32", JSONName: "fUInt32", - Typez: genclient.UINT32_TYPE, + Typez: api.UINT32_TYPE, TypezID: "uint32"}, { Repeated: true, Name: "fString", JSONName: "fString", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: "string"}, { Repeated: true, Name: "fSInt64", JSONName: "fSInt64", - Typez: genclient.INT64_TYPE, + Typez: api.INT64_TYPE, TypezID: "int64"}, { Repeated: true, Name: "fSUInt64", JSONName: "fSUInt64", - Typez: genclient.UINT64_TYPE, + Typez: api.UINT64_TYPE, TypezID: "uint64"}, { Repeated: true, Name: "fDuration", JSONName: "fDuration", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.Duration", }, { Repeated: true, Name: "fTimestamp", JSONName: "fTimestamp", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.Timestamp", }, { Repeated: true, Name: "fFieldMask", JSONName: "fFieldMask", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.FieldMask", }, { Repeated: true, Name: "fBytes", JSONName: "fBytes", - Typez: genclient.BYTES_TYPE, + Typez: api.BYTES_TYPE, TypezID: "bytes", }, }, @@ -368,20 +368,20 @@ func TestOpenAPI_SimpleObject(t *testing.T) { if err != nil { t.Fatal(err) } - api, err := makeAPIForOpenAPI(nil, model) + test, err := makeAPIForOpenAPI(nil, model) if err != nil { t.Fatalf("Error in makeAPI() %q", err) } - checkMessage(t, *api.Messages[0], genclient.Message{ + checkMessage(t, *api.Messages[0], api.Message{ Name: "Fake", ID: "..Fake", Documentation: "A test message.", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "fObject", JSONName: "fObject", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: "..Foo", Documentation: "An object field.", Optional: true, @@ -389,7 +389,7 @@ func TestOpenAPI_SimpleObject(t *testing.T) { { Name: "fObjectArray", JSONName: "fObjectArray", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: "..Bar", Documentation: "An object array field.", Optional: false, @@ -415,17 +415,17 @@ func TestOpenAPI_Any(t *testing.T) { if err != nil { t.Fatal(err) } - api, err := makeAPIForOpenAPI(nil, model) + test, err := makeAPIForOpenAPI(nil, model) if err != nil { t.Errorf("Error in makeAPI() %q", err) } - checkMessage(t, *api.Messages[0], genclient.Message{ + checkMessage(t, *api.Messages[0], api.Message{ Name: "Fake", ID: "..Fake", Documentation: "A test message.", - Fields: []*genclient.Field{ - {Name: "fMap", JSONName: "fMap", Typez: genclient.MESSAGE_TYPE, TypezID: ".google.protobuf.Any", Optional: true}, + Fields: []*api.Field{ + {Name: "fMap", JSONName: "fMap", Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.Any", Optional: true}, }, }) } @@ -448,32 +448,32 @@ func TestOpenAPI_MapString(t *testing.T) { if err != nil { t.Fatal(err) } - api, err := makeAPIForOpenAPI(nil, model) + test, err := makeAPIForOpenAPI(nil, model) if err != nil { t.Fatal(err) } - checkMessage(t, *api.Messages[0], genclient.Message{ + checkMessage(t, *api.Messages[0], api.Message{ Name: "Fake", ID: "..Fake", Documentation: "A test message.", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "fMap", JSONName: "fMap", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: "$map", }, { Name: "fMapS32", JSONName: "fMapS32", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: "$map", }, { Name: "fMapS64", JSONName: "fMapS64", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: "$map", }, }, @@ -497,26 +497,26 @@ func TestOpenAPI_MapInteger(t *testing.T) { if err != nil { t.Fatal(err) } - api, err := makeAPIForOpenAPI(nil, model) + test, err := makeAPIForOpenAPI(nil, model) if err != nil { t.Errorf("Error in makeAPI() %q", err) } - checkMessage(t, *api.Messages[0], genclient.Message{ + checkMessage(t, *api.Messages[0], api.Message{ Name: "Fake", ID: "..Fake", Documentation: "A test message.", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "fMapI32", JSONName: "fMapI32", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: "$map", Optional: false}, { Name: "fMapI64", JSONName: "fMapI64", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: "$map", Optional: false}, }, @@ -532,26 +532,26 @@ func TestOpenAPI_MakeAPI(t *testing.T) { if err != nil { t.Fatal(err) } - api, err := makeAPIForOpenAPI(nil, model) + test, err := makeAPIForOpenAPI(nil, model) if err != nil { t.Fatalf("Error in makeAPI() %q", err) } - location := api.State.MessageByID["..Location"] + location := test.State.MessageByID["..Location"] if location == nil { t.Errorf("missing message (Location) in MessageByID index") return } - checkMessage(t, *location, genclient.Message{ + checkMessage(t, *location, api.Message{ Documentation: "A resource that represents a Google Cloud location.", Name: "Location", ID: "..Location", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "name", JSONName: "name", Documentation: "Resource name for the location, which may vary between implementations." + "\nFor example: `\"projects/example-project/locations/us-east1\"`", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: "string", Optional: true, }, @@ -559,7 +559,7 @@ func TestOpenAPI_MakeAPI(t *testing.T) { Name: "locationId", JSONName: "locationId", Documentation: "The canonical id for this location. For example: `\"us-east1\"`.", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: "string", Optional: true, }, @@ -567,7 +567,7 @@ func TestOpenAPI_MakeAPI(t *testing.T) { Name: "displayName", JSONName: "displayName", Documentation: `The friendly name for this location, typically a nearby city name.` + "\n" + `For example, "Tokyo".`, - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: "string", Optional: true, }, @@ -575,7 +575,7 @@ func TestOpenAPI_MakeAPI(t *testing.T) { Name: "labels", JSONName: "labels", Documentation: "Cross-service attributes for the location. For example\n\n {\"cloud.googleapis.com/region\": \"us-east1\"}", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: "$map", Optional: false, }, @@ -583,28 +583,28 @@ func TestOpenAPI_MakeAPI(t *testing.T) { Name: "metadata", JSONName: "metadata", Documentation: `Service-specific metadata. For example the available capacity at the given` + "\n" + `location.`, - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.Any", Optional: true, }, }, }) - listLocationsResponse := api.State.MessageByID["..ListLocationsResponse"] + listLocationsResponse := test.State.MessageByID["..ListLocationsResponse"] if listLocationsResponse == nil { t.Errorf("missing message (ListLocationsResponse) in MessageByID index") return } - checkMessage(t, *listLocationsResponse, genclient.Message{ + checkMessage(t, *listLocationsResponse, api.Message{ Documentation: "The response message for Locations.ListLocations.", Name: "ListLocationsResponse", ID: "..ListLocationsResponse", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "locations", JSONName: "locations", Documentation: "A list of locations that matches the specified filter in the request.", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: "..Location", Repeated: true, }, @@ -612,7 +612,7 @@ func TestOpenAPI_MakeAPI(t *testing.T) { Name: "nextPageToken", JSONName: "nextPageToken", Documentation: "The standard List next-page token.", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: "string", Optional: true, }, @@ -621,21 +621,21 @@ func TestOpenAPI_MakeAPI(t *testing.T) { // This is a synthetic message, the OpenAPI spec does not contain requests // messages for messages without a body. - listLocationsRequest, ok := api.State.MessageByID["..ListLocationsRequest"] + listLocationsRequest, ok := test.State.MessageByID["..ListLocationsRequest"] if !ok { t.Errorf("missing message (ListLocationsRequest) in MessageByID index") return } - checkMessage(t, *listLocationsRequest, genclient.Message{ + checkMessage(t, *listLocationsRequest, api.Message{ Name: "ListLocationsRequest", ID: "..ListLocationsRequest", Documentation: "The request message for ListLocations.", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "project", JSONName: "project", Documentation: "The `{project}` component of the target path.\n\nThe full target path will be in the form `/v1/projects/{project}/locations`.", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: "string", Synthetic: true, }, @@ -646,7 +646,7 @@ func TestOpenAPI_MakeAPI(t *testing.T) { "\nThe filtering language accepts strings like `\"displayName=tokyo" + "\"`, and\nis documented in more detail in [AIP-160](https://google" + ".aip.dev/160).", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: "string", Optional: true, Synthetic: true, @@ -655,7 +655,7 @@ func TestOpenAPI_MakeAPI(t *testing.T) { Name: "pageSize", JSONName: "pageSize", Documentation: "The maximum number of results to return.\nIf not set, the service selects a default.", - Typez: genclient.INT32_TYPE, + Typez: api.INT32_TYPE, TypezID: "int32", Optional: true, Synthetic: true, @@ -664,7 +664,7 @@ func TestOpenAPI_MakeAPI(t *testing.T) { Name: "pageToken", JSONName: "pageToken", Documentation: "A page token received from the `next_page_token` field in the response.\nSend that page token to receive the subsequent page.", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: "string", Optional: true, Synthetic: true, @@ -673,21 +673,21 @@ func TestOpenAPI_MakeAPI(t *testing.T) { }) // This message has a weirdly named field that gets tricky to serialize. - secretPayload, ok := api.State.MessageByID["..SecretPayload"] + secretPayload, ok := test.State.MessageByID["..SecretPayload"] if !ok { t.Errorf("missing message (SecretPayload) in MessageByID index") return } - checkMessage(t, *secretPayload, genclient.Message{ + checkMessage(t, *secretPayload, api.Message{ Name: "SecretPayload", ID: "..SecretPayload", Documentation: "A secret payload resource in the Secret Manager API. This contains the\nsensitive secret payload that is associated with a SecretVersion.", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "data", JSONName: "data", Documentation: "The secret data. Must be no larger than 64KiB.", - Typez: genclient.BYTES_TYPE, + Typez: api.BYTES_TYPE, TypezID: "bytes", Optional: true, }, @@ -695,42 +695,42 @@ func TestOpenAPI_MakeAPI(t *testing.T) { Name: "dataCrc32c", JSONName: "dataCrc32c", Documentation: "Optional. If specified, SecretManagerService will verify the integrity of the\nreceived data on SecretManagerService.AddSecretVersion calls using\nthe crc32c checksum and store it to include in future\nSecretManagerService.AccessSecretVersion responses. If a checksum is\nnot provided in the SecretManagerService.AddSecretVersion request, the\nSecretManagerService will generate and store one for you.\n\nThe CRC32C value is encoded as a Int64 for compatibility, and can be\nsafely downconverted to uint32 in languages that support this type.\nhttps://cloud.google.com/apis/design/design_patterns#integer_types", - Typez: genclient.INT64_TYPE, + Typez: api.INT64_TYPE, TypezID: "int64", Optional: true, }, }, }) - service, ok := api.State.ServiceByID["..Service"] + service, ok := test.State.ServiceByID["..Service"] if !ok { t.Errorf("missing service (Service) in ServiceByID index") return } - wantService := &genclient.Service{ + wantService := &api.Service{ Name: "Service", ID: "..Service", Documentation: "Stores sensitive data such as API keys, passwords, and certificates. Provides convenience while improving security.", DefaultHost: "secretmanager.googleapis.com", } - if diff := cmp.Diff(wantService, service, cmpopts.IgnoreFields(genclient.Service{}, "Methods")); diff != "" { + if diff := cmp.Diff(wantService, service, cmpopts.IgnoreFields(api.Service{}, "Methods")); diff != "" { t.Errorf("mismatched service attributes (-want, +got):\n%s", diff) } - checkMethod(t, service, "ListLocations", &genclient.Method{ + checkMethod(t, service, "ListLocations", &api.Method{ Name: "ListLocations", ID: "..Service.ListLocations", Documentation: "Lists information about the supported locations for this service.", InputTypeID: "..ListLocationsRequest", OutputTypeID: "..ListLocationsResponse", - PathInfo: &genclient.PathInfo{ + PathInfo: &api.PathInfo{ Verb: "GET", - PathTemplate: []genclient.PathSegment{ - genclient.NewLiteralPathSegment("v1"), - genclient.NewLiteralPathSegment("projects"), - genclient.NewFieldPathPathSegment("project"), - genclient.NewLiteralPathSegment("locations"), + PathTemplate: []api.PathSegment{ + api.NewLiteralPathSegment("v1"), + api.NewLiteralPathSegment("projects"), + api.NewFieldPathPathSegment("project"), + api.NewLiteralPathSegment("locations"), }, QueryParameters: map[string]bool{ "filter": true, @@ -740,20 +740,20 @@ func TestOpenAPI_MakeAPI(t *testing.T) { }, }) - checkMethod(t, service, "CreateSecret", &genclient.Method{ + checkMethod(t, service, "CreateSecret", &api.Method{ Name: "CreateSecret", ID: "..Service.CreateSecret", Documentation: "Creates a new Secret containing no SecretVersions.", InputTypeID: "..CreateSecretRequest", OutputTypeID: "..Secret", - PathInfo: &genclient.PathInfo{ + PathInfo: &api.PathInfo{ Verb: "POST", BodyFieldPath: "requestBody", - PathTemplate: []genclient.PathSegment{ - genclient.NewLiteralPathSegment("v1"), - genclient.NewLiteralPathSegment("projects"), - genclient.NewFieldPathPathSegment("project"), - genclient.NewLiteralPathSegment("secrets"), + PathTemplate: []api.PathSegment{ + api.NewLiteralPathSegment("v1"), + api.NewLiteralPathSegment("projects"), + api.NewFieldPathPathSegment("project"), + api.NewLiteralPathSegment("secrets"), }, QueryParameters: map[string]bool{ "secretId": true, @@ -761,22 +761,22 @@ func TestOpenAPI_MakeAPI(t *testing.T) { }, }) - checkMethod(t, service, "AddSecretVersion", &genclient.Method{ + checkMethod(t, service, "AddSecretVersion", &api.Method{ Name: "AddSecretVersion", ID: "..Service.AddSecretVersion", Documentation: "Creates a new SecretVersion containing secret data and attaches\nit to an existing Secret.", InputTypeID: "..AddSecretVersionRequest", OutputTypeID: "..SecretVersion", - PathInfo: &genclient.PathInfo{ + PathInfo: &api.PathInfo{ Verb: "POST", BodyFieldPath: "*", - PathTemplate: []genclient.PathSegment{ - genclient.NewLiteralPathSegment("v1"), - genclient.NewLiteralPathSegment("projects"), - genclient.NewFieldPathPathSegment("project"), - genclient.NewLiteralPathSegment("secrets"), - genclient.NewFieldPathPathSegment("secret"), - genclient.NewVerbPathSegment("addVersion"), + PathTemplate: []api.PathSegment{ + api.NewLiteralPathSegment("v1"), + api.NewLiteralPathSegment("projects"), + api.NewFieldPathPathSegment("project"), + api.NewLiteralPathSegment("secrets"), + api.NewFieldPathPathSegment("secret"), + api.NewVerbPathSegment("addVersion"), }, QueryParameters: map[string]bool{}, }, @@ -792,28 +792,28 @@ func TestOpenAPI_SyntheticMessageWithExistingRequest(t *testing.T) { if err != nil { t.Fatal(err) } - api, err := makeAPIForOpenAPI(nil, model) + test, err := makeAPIForOpenAPI(nil, model) if err != nil { t.Fatalf("Error in makeAPI() %q", err) } // This message has a weirdly named field that gets tricky to serialize. id := "..SetIamPolicyRequest" - setIamPolicyRequest, ok := api.State.MessageByID["..SetIamPolicyRequest"] + setIamPolicyRequest, ok := test.State.MessageByID["..SetIamPolicyRequest"] if !ok { t.Errorf("missing message (%s) in MessageByID index", id) return } - checkMessage(t, *setIamPolicyRequest, genclient.Message{ + checkMessage(t, *setIamPolicyRequest, api.Message{ Name: "SetIamPolicyRequest", ID: "..SetIamPolicyRequest", Documentation: "Request message for `SetIamPolicy` method.", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "policy", JSONName: "policy", Documentation: "REQUIRED: The complete policy to be applied to the `resource`. The size of\nthe policy is limited to a few 10s of KB. An empty policy is a\nvalid policy but certain Google Cloud services (such as Projects)\nmight reject them.", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: "..Policy", Optional: true, }, @@ -821,7 +821,7 @@ func TestOpenAPI_SyntheticMessageWithExistingRequest(t *testing.T) { Name: "updateMask", JSONName: "updateMask", Documentation: "OPTIONAL: A FieldMask specifying which fields of the policy to modify. Only\nthe fields in the mask will be modified. If no mask is provided, the\nfollowing default mask is used:\n\n`paths: \"bindings, etag\"`", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.FieldMask", Optional: true, }, @@ -829,7 +829,7 @@ func TestOpenAPI_SyntheticMessageWithExistingRequest(t *testing.T) { Name: "project", JSONName: "project", Documentation: "The `{project}` component of the target path.\n\nThe full target path will be in the form `/v1/projects/{project}/secrets/{secret}:setIamPolicy`.", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: "string", Synthetic: true, }, @@ -837,7 +837,7 @@ func TestOpenAPI_SyntheticMessageWithExistingRequest(t *testing.T) { Name: "secret", JSONName: "secret", Documentation: "The `{secret}` component of the target path.\n\nThe full target path will be in the form `/v1/projects/{project}/secrets/{secret}:setIamPolicy`.", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: "string", Synthetic: true, }, @@ -845,7 +845,7 @@ func TestOpenAPI_SyntheticMessageWithExistingRequest(t *testing.T) { Name: "location", JSONName: "location", Documentation: "The `{location}` component of the target path.\n\nThe full target path will be in the form `/v1/projects/{project}/locations/{location}/secrets/{secret}:setIamPolicy`.", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, TypezID: "string", Synthetic: true, }, diff --git a/generator/internal/parser/protobuf.go b/generator/internal/parser/protobuf.go index 38d06fc44..d1a4b494d 100644 --- a/generator/internal/parser/protobuf.go +++ b/generator/internal/parser/protobuf.go @@ -24,6 +24,7 @@ import ( "path/filepath" "strings" + "github.com/googleapis/google-cloud-rust/generator/internal/api" "github.com/googleapis/google-cloud-rust/generator/internal/genclient" "google.golang.org/genproto/googleapis/api/serviceconfig" "google.golang.org/protobuf/proto" @@ -32,8 +33,8 @@ import ( ) // ParserProtobuf reads Protobuf specifications and converts them into -// the `genclient.API` model. -func ParseProtobuf(opts genclient.ParserOptions) (*genclient.API, error) { +// the `api.API` model. +func ParseProtobuf(opts genclient.ParserOptions) (*api.API, error) { request, err := newCodeGeneratorRequest(opts) if err != nil { return nil, err @@ -206,21 +207,23 @@ const ( enumDescriptorValue = 2 ) -func makeAPIForProtobuf(serviceConfig *serviceconfig.Service, req *pluginpb.CodeGeneratorRequest) *genclient.API { - var mixinFileDesc []*descriptorpb.FileDescriptorProto - var enabledMixinMethods mixinMethods = make(map[string]bool) - state := &genclient.APIState{ - ServiceByID: make(map[string]*genclient.Service), - MethodByID: make(map[string]*genclient.Method), - MessageByID: make(map[string]*genclient.Message), - EnumByID: make(map[string]*genclient.Enum), +func makeAPIForProtobuf(serviceConfig *serviceconfig.Service, req *pluginpb.CodeGeneratorRequest) *api.API { + var ( + mixinFileDesc []*descriptorpb.FileDescriptorProto + enabledMixinMethods mixinMethods = make(map[string]bool) + ) + state := &api.APIState{ + ServiceByID: make(map[string]*api.Service), + MethodByID: make(map[string]*api.Method), + MessageByID: make(map[string]*api.Message), + EnumByID: make(map[string]*api.Enum), } - api := &genclient.API{ + a := &api.API{ State: state, } if serviceConfig != nil { - api.Title = serviceConfig.Title - api.Description = serviceConfig.Documentation.Summary + a.Title = serviceConfig.Title + a.Description = serviceConfig.Documentation.Summary enabledMixinMethods, mixinFileDesc = loadMixins(serviceConfig) packageName := "" for _, api := range serviceConfig.Apis { @@ -230,7 +233,7 @@ func makeAPIForProtobuf(serviceConfig *serviceconfig.Service, req *pluginpb.Code break } } - api.PackageName = packageName + a.PackageName = packageName } // First we need to add all the message and enums types to the @@ -253,14 +256,14 @@ func makeAPIForProtobuf(serviceConfig *serviceconfig.Service, req *pluginpb.Code // Then we need to add the messages, enums and services to the list of // elements to be generated. for _, f := range req.GetSourceFileDescriptors() { - var fileServices []*genclient.Service + var fileServices []*api.Service fFQN := "." + f.GetPackage() // Messages for _, m := range f.MessageType { mFQN := fFQN + "." + m.GetName() if msg, ok := state.MessageByID[mFQN]; ok { - api.Messages = append(api.Messages, msg) + a.Messages = append(a.Messages, msg) } else { slog.Warn("missing message in symbol table", "message", mFQN) } @@ -270,7 +273,7 @@ func makeAPIForProtobuf(serviceConfig *serviceconfig.Service, req *pluginpb.Code for _, e := range f.EnumType { eFQN := fFQN + "." + e.GetName() if e, ok := state.EnumByID[eFQN]; ok { - api.Enums = append(api.Enums, e) + a.Enums = append(a.Enums, e) } else { slog.Warn("missing enum in symbol table", "message", eFQN) } @@ -312,12 +315,12 @@ func makeAPIForProtobuf(serviceConfig *serviceconfig.Service, req *pluginpb.Code slog.Warn("file dropped documentation", "loc", p, "docs", loc.GetLeadingComments()) } } - api.Services = append(api.Services, fileServices...) + a.Services = append(a.Services, fileServices...) } // Handle mixins for _, f := range mixinFileDesc { - var fileServices []*genclient.Service + var fileServices []*api.Service fFQN := "." + f.GetPackage() for _, s := range f.Service { sFQN := fFQN + "." + s.GetName() @@ -333,39 +336,39 @@ func makeAPIForProtobuf(serviceConfig *serviceconfig.Service, req *pluginpb.Code } fileServices = append(fileServices, service) } - api.Services = append(api.Services, fileServices...) + a.Services = append(a.Services, fileServices...) } - updateMixinState(serviceConfig, api) - if api.Name == "" && serviceConfig != nil { - api.Name = strings.TrimSuffix(serviceConfig.Name, ".googleapis.com") + updateMixinState(serviceConfig, a) + if a.Name == "" && serviceConfig != nil { + a.Name = strings.TrimSuffix(serviceConfig.Name, ".googleapis.com") } - return api + return a } -var descriptorpbToTypez = map[descriptorpb.FieldDescriptorProto_Type]genclient.Typez{ - descriptorpb.FieldDescriptorProto_TYPE_DOUBLE: genclient.DOUBLE_TYPE, - descriptorpb.FieldDescriptorProto_TYPE_FLOAT: genclient.FLOAT_TYPE, - descriptorpb.FieldDescriptorProto_TYPE_INT64: genclient.INT64_TYPE, - descriptorpb.FieldDescriptorProto_TYPE_UINT64: genclient.UINT64_TYPE, - descriptorpb.FieldDescriptorProto_TYPE_INT32: genclient.INT32_TYPE, - descriptorpb.FieldDescriptorProto_TYPE_FIXED64: genclient.FIXED64_TYPE, - descriptorpb.FieldDescriptorProto_TYPE_FIXED32: genclient.FIXED32_TYPE, - descriptorpb.FieldDescriptorProto_TYPE_BOOL: genclient.BOOL_TYPE, - descriptorpb.FieldDescriptorProto_TYPE_STRING: genclient.STRING_TYPE, - descriptorpb.FieldDescriptorProto_TYPE_BYTES: genclient.BYTES_TYPE, - descriptorpb.FieldDescriptorProto_TYPE_UINT32: genclient.UINT32_TYPE, - descriptorpb.FieldDescriptorProto_TYPE_SFIXED32: genclient.SFIXED32_TYPE, - descriptorpb.FieldDescriptorProto_TYPE_SFIXED64: genclient.SFIXED64_TYPE, - descriptorpb.FieldDescriptorProto_TYPE_SINT32: genclient.SINT32_TYPE, - descriptorpb.FieldDescriptorProto_TYPE_SINT64: genclient.SINT64_TYPE, - descriptorpb.FieldDescriptorProto_TYPE_GROUP: genclient.GROUP_TYPE, - descriptorpb.FieldDescriptorProto_TYPE_MESSAGE: genclient.MESSAGE_TYPE, - descriptorpb.FieldDescriptorProto_TYPE_ENUM: genclient.ENUM_TYPE, +var descriptorpbToTypez = map[descriptorpb.FieldDescriptorProto_Type]api.Typez{ + descriptorpb.FieldDescriptorProto_TYPE_DOUBLE: api.DOUBLE_TYPE, + descriptorpb.FieldDescriptorProto_TYPE_FLOAT: api.FLOAT_TYPE, + descriptorpb.FieldDescriptorProto_TYPE_INT64: api.INT64_TYPE, + descriptorpb.FieldDescriptorProto_TYPE_UINT64: api.UINT64_TYPE, + descriptorpb.FieldDescriptorProto_TYPE_INT32: api.INT32_TYPE, + descriptorpb.FieldDescriptorProto_TYPE_FIXED64: api.FIXED64_TYPE, + descriptorpb.FieldDescriptorProto_TYPE_FIXED32: api.FIXED32_TYPE, + descriptorpb.FieldDescriptorProto_TYPE_BOOL: api.BOOL_TYPE, + descriptorpb.FieldDescriptorProto_TYPE_STRING: api.STRING_TYPE, + descriptorpb.FieldDescriptorProto_TYPE_BYTES: api.BYTES_TYPE, + descriptorpb.FieldDescriptorProto_TYPE_UINT32: api.UINT32_TYPE, + descriptorpb.FieldDescriptorProto_TYPE_SFIXED32: api.SFIXED32_TYPE, + descriptorpb.FieldDescriptorProto_TYPE_SFIXED64: api.SFIXED64_TYPE, + descriptorpb.FieldDescriptorProto_TYPE_SINT32: api.SINT32_TYPE, + descriptorpb.FieldDescriptorProto_TYPE_SINT64: api.SINT64_TYPE, + descriptorpb.FieldDescriptorProto_TYPE_GROUP: api.GROUP_TYPE, + descriptorpb.FieldDescriptorProto_TYPE_MESSAGE: api.MESSAGE_TYPE, + descriptorpb.FieldDescriptorProto_TYPE_ENUM: api.ENUM_TYPE, } -func normalizeTypes(state *genclient.APIState, in *descriptorpb.FieldDescriptorProto, field *genclient.Field) { +func normalizeTypes(state *api.APIState, in *descriptorpb.FieldDescriptorProto, field *api.Field) { typ := in.GetType() - field.Typez = genclient.UNDEFINED_TYPE + field.Typez = api.UNDEFINED_TYPE if tz, ok := descriptorpbToTypez[typ]; ok { field.Typez = tz } @@ -415,8 +418,8 @@ func normalizeTypes(state *genclient.APIState, in *descriptorpb.FieldDescriptorP } -func processService(state *genclient.APIState, s *descriptorpb.ServiceDescriptorProto, sFQN, packagez string) *genclient.Service { - service := &genclient.Service{ +func processService(state *api.APIState, s *descriptorpb.ServiceDescriptorProto, sFQN, packagez string) *api.Service { + service := &api.Service{ Name: s.GetName(), ID: sFQN, Package: packagez, @@ -426,13 +429,13 @@ func processService(state *genclient.APIState, s *descriptorpb.ServiceDescriptor return service } -func processMethod(state *genclient.APIState, m *descriptorpb.MethodDescriptorProto, mFQN string) *genclient.Method { +func processMethod(state *api.APIState, m *descriptorpb.MethodDescriptorProto, mFQN string) *api.Method { pathInfo, err := parsePathInfo(m, state) if err != nil { slog.Error("unsupported http method", "method", m) return nil } - method := &genclient.Method{ + method := &api.Method{ ID: mFQN, PathInfo: pathInfo, Name: m.GetName(), @@ -443,8 +446,8 @@ func processMethod(state *genclient.APIState, m *descriptorpb.MethodDescriptorPr return method } -func processMessage(state *genclient.APIState, m *descriptorpb.DescriptorProto, mFQN, packagez string, parent *genclient.Message) *genclient.Message { - message := &genclient.Message{ +func processMessage(state *api.APIState, m *descriptorpb.DescriptorProto, mFQN, packagez string, parent *api.Message) *api.Message { + message := &api.Message{ Name: m.GetName(), ID: mFQN, Parent: parent, @@ -467,7 +470,7 @@ func processMessage(state *genclient.APIState, m *descriptorpb.DescriptorProto, message.Enums = append(message.Enums, e) } for _, oneof := range m.OneofDecl { - oneOfs := &genclient.OneOf{ + oneOfs := &api.OneOf{ Name: oneof.GetName(), ID: mFQN + "." + oneof.GetName(), Parent: message, @@ -476,7 +479,7 @@ func processMessage(state *genclient.APIState, m *descriptorpb.DescriptorProto, } for _, mf := range m.Field { isProtoOptional := mf.Proto3Optional != nil && *mf.Proto3Optional - field := &genclient.Field{ + field := &api.Field{ Name: mf.GetName(), ID: mFQN + "." + mf.GetName(), JSONName: mf.GetJsonName(), @@ -508,15 +511,15 @@ func processMessage(state *genclient.APIState, m *descriptorpb.DescriptorProto, return message } -func processEnum(state *genclient.APIState, e *descriptorpb.EnumDescriptorProto, eFQN, packagez string, parent *genclient.Message) *genclient.Enum { - enum := &genclient.Enum{ +func processEnum(state *api.APIState, e *descriptorpb.EnumDescriptorProto, eFQN, packagez string, parent *api.Message) *api.Enum { + enum := &api.Enum{ Name: e.GetName(), Parent: parent, Package: packagez, } state.EnumByID[eFQN] = enum for _, ev := range e.Value { - enumValue := &genclient.EnumValue{ + enumValue := &api.EnumValue{ Name: ev.GetName(), Number: ev.GetNumber(), Parent: enum, @@ -526,7 +529,7 @@ func processEnum(state *genclient.APIState, e *descriptorpb.EnumDescriptorProto, return enum } -func addServiceDocumentation(state *genclient.APIState, p []int32, doc string, sFQN string) { +func addServiceDocumentation(state *api.APIState, p []int32, doc string, sFQN string) { if len(p) == 0 { // This is a comment for a service state.ServiceByID[sFQN].Documentation = trimLeadingSpacesInDocumentation(doc) @@ -538,7 +541,7 @@ func addServiceDocumentation(state *genclient.APIState, p []int32, doc string, s } } -func addMessageDocumentation(state *genclient.APIState, m *descriptorpb.DescriptorProto, p []int32, doc string, mFQN string) { +func addMessageDocumentation(state *api.APIState, m *descriptorpb.DescriptorProto, p []int32, doc string, mFQN string) { // Beware of refactoring the calls to `trimLeadingSpacesInDocumentation`. // We should modify `doc` only once, upon assignment to `.Documentation` if len(p) == 0 { @@ -561,7 +564,7 @@ func addMessageDocumentation(state *genclient.APIState, m *descriptorpb.Descript } // addEnumDocumentation adds documentation to an enum. -func addEnumDocumentation(state *genclient.APIState, p []int32, doc string, eFQN string) { +func addEnumDocumentation(state *api.APIState, p []int32, doc string, eFQN string) { if len(p) == 0 { // This is a comment for an enum state.EnumByID[eFQN].Documentation = trimLeadingSpacesInDocumentation(doc) diff --git a/generator/internal/parser/protobuf_test.go b/generator/internal/parser/protobuf_test.go index beca9350c..4658d0775 100644 --- a/generator/internal/parser/protobuf_test.go +++ b/generator/internal/parser/protobuf_test.go @@ -18,6 +18,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "github.com/googleapis/google-cloud-rust/generator/internal/api" "github.com/googleapis/google-cloud-rust/generator/internal/genclient" "google.golang.org/genproto/googleapis/api/annotations" "google.golang.org/genproto/googleapis/api/serviceconfig" @@ -35,22 +36,21 @@ func TestProtobuf_Info(t *testing.T) { }, } - api := makeAPIForProtobuf(serviceConfig, newTestCodeGeneratorRequest(t, "scalar.proto")) - if api.Name != "secretmanager" { - t.Errorf("want = %q; got = %q", "secretmanager", api.Name) + test := makeAPIForProtobuf(serviceConfig, newTestCodeGeneratorRequest(t, "scalar.proto")) + if test.Name != "secretmanager" { + t.Errorf("want = %q; got = %q", "secretmanager", test.Name) } - if api.Title != serviceConfig.Title { - t.Errorf("want = %q; got = %q", serviceConfig.Title, api.Name) + if test.Title != serviceConfig.Title { + t.Errorf("want = %q; got = %q", serviceConfig.Title, test.Name) } - if diff := cmp.Diff(api.Description, serviceConfig.Documentation.Summary); diff != "" { + if diff := cmp.Diff(test.Description, serviceConfig.Documentation.Summary); diff != "" { t.Errorf("description mismatch (-want, +got):\n%s", diff) } } func TestProtobuf_Scalar(t *testing.T) { - api := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "scalar.proto")) - - message, ok := api.State.MessageByID[".test.Fake"] + test := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "scalar.proto")) + message, ok := test.State.MessageByID[".test.Fake"] if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Fake") } @@ -59,120 +59,119 @@ func TestProtobuf_Scalar(t *testing.T) { Package: "test", ID: ".test.Fake", Documentation: "A test message.", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Documentation: "A singular field tag = 1", Name: "f_double", JSONName: "fDouble", ID: ".test.Fake.f_double", - Typez: genclient.DOUBLE_TYPE, + Typez: api.DOUBLE_TYPE, }, { Documentation: "A singular field tag = 2", Name: "f_float", JSONName: "fFloat", ID: ".test.Fake.f_float", - Typez: genclient.FLOAT_TYPE, + Typez: api.FLOAT_TYPE, }, { Documentation: "A singular field tag = 3", Name: "f_int64", JSONName: "fInt64", ID: ".test.Fake.f_int64", - Typez: genclient.INT64_TYPE, + Typez: api.INT64_TYPE, }, { Documentation: "A singular field tag = 4", Name: "f_uint64", JSONName: "fUint64", ID: ".test.Fake.f_uint64", - Typez: genclient.UINT64_TYPE, + Typez: api.UINT64_TYPE, }, { Documentation: "A singular field tag = 5", Name: "f_int32", JSONName: "fInt32", ID: ".test.Fake.f_int32", - Typez: genclient.INT32_TYPE, + Typez: api.INT32_TYPE, }, { Documentation: "A singular field tag = 6", Name: "f_fixed64", JSONName: "fFixed64", ID: ".test.Fake.f_fixed64", - Typez: genclient.FIXED64_TYPE, + Typez: api.FIXED64_TYPE, }, { Documentation: "A singular field tag = 7", Name: "f_fixed32", JSONName: "fFixed32", ID: ".test.Fake.f_fixed32", - Typez: genclient.FIXED32_TYPE, + Typez: api.FIXED32_TYPE, }, { Documentation: "A singular field tag = 8", Name: "f_bool", JSONName: "fBool", ID: ".test.Fake.f_bool", - Typez: genclient.BOOL_TYPE, + Typez: api.BOOL_TYPE, }, { Documentation: "A singular field tag = 9", Name: "f_string", JSONName: "fString", ID: ".test.Fake.f_string", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, }, { Documentation: "A singular field tag = 12", Name: "f_bytes", JSONName: "fBytes", ID: ".test.Fake.f_bytes", - Typez: genclient.BYTES_TYPE, + Typez: api.BYTES_TYPE, }, { Documentation: "A singular field tag = 13", Name: "f_uint32", JSONName: "fUint32", ID: ".test.Fake.f_uint32", - Typez: genclient.UINT32_TYPE, + Typez: api.UINT32_TYPE, }, { Documentation: "A singular field tag = 15", Name: "f_sfixed32", JSONName: "fSfixed32", ID: ".test.Fake.f_sfixed32", - Typez: genclient.SFIXED32_TYPE, + Typez: api.SFIXED32_TYPE, }, { Documentation: "A singular field tag = 16", Name: "f_sfixed64", JSONName: "fSfixed64", ID: ".test.Fake.f_sfixed64", - Typez: genclient.SFIXED64_TYPE, + Typez: api.SFIXED64_TYPE, }, { Documentation: "A singular field tag = 17", Name: "f_sint32", JSONName: "fSint32", ID: ".test.Fake.f_sint32", - Typez: genclient.SINT32_TYPE, + Typez: api.SINT32_TYPE, }, { Documentation: "A singular field tag = 18", Name: "f_sint64", JSONName: "fSint64", ID: ".test.Fake.f_sint64", - Typez: genclient.SINT64_TYPE, + Typez: api.SINT64_TYPE, }, }, }) } func TestProtobuf_ScalarArray(t *testing.T) { - api := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "scalar_array.proto")) - - message, ok := api.State.MessageByID[".test.Fake"] + test := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "scalar_array.proto")) + message, ok := test.State.MessageByID[".test.Fake"] if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Fake") } @@ -181,14 +180,14 @@ func TestProtobuf_ScalarArray(t *testing.T) { Package: "test", ID: ".test.Fake", Documentation: "A test message.", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Repeated: true, Documentation: "A repeated field tag = 1", Name: "f_double", JSONName: "fDouble", ID: ".test.Fake.f_double", - Typez: genclient.DOUBLE_TYPE, + Typez: api.DOUBLE_TYPE, }, { Repeated: true, @@ -196,7 +195,7 @@ func TestProtobuf_ScalarArray(t *testing.T) { Name: "f_int64", JSONName: "fInt64", ID: ".test.Fake.f_int64", - Typez: genclient.INT64_TYPE, + Typez: api.INT64_TYPE, }, { Repeated: true, @@ -204,7 +203,7 @@ func TestProtobuf_ScalarArray(t *testing.T) { Name: "f_string", JSONName: "fString", ID: ".test.Fake.f_string", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, }, { Repeated: true, @@ -212,16 +211,15 @@ func TestProtobuf_ScalarArray(t *testing.T) { Name: "f_bytes", JSONName: "fBytes", ID: ".test.Fake.f_bytes", - Typez: genclient.BYTES_TYPE, + Typez: api.BYTES_TYPE, }, }, }) } func TestProtobuf_ScalarOptional(t *testing.T) { - api := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "scalar_optional.proto")) - - message, ok := api.State.MessageByID[".test.Fake"] + test := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "scalar_optional.proto")) + message, ok := test.State.MessageByID[".test.Fake"] if !ok { t.Fatalf("Cannot find message %s in API", "Fake") } @@ -230,14 +228,14 @@ func TestProtobuf_ScalarOptional(t *testing.T) { Package: "test", ID: ".test.Fake", Documentation: "A test message.", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Optional: true, Documentation: "An optional field tag = 1", Name: "f_double", JSONName: "fDouble", ID: ".test.Fake.f_double", - Typez: genclient.DOUBLE_TYPE, + Typez: api.DOUBLE_TYPE, }, { Optional: true, @@ -245,7 +243,7 @@ func TestProtobuf_ScalarOptional(t *testing.T) { Name: "f_int64", JSONName: "fInt64", ID: ".test.Fake.f_int64", - Typez: genclient.INT64_TYPE, + Typez: api.INT64_TYPE, }, { Optional: true, @@ -253,7 +251,7 @@ func TestProtobuf_ScalarOptional(t *testing.T) { Name: "f_string", JSONName: "fString", ID: ".test.Fake.f_string", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, }, { Optional: true, @@ -261,21 +259,20 @@ func TestProtobuf_ScalarOptional(t *testing.T) { Name: "f_bytes", JSONName: "fBytes", ID: ".test.Fake.f_bytes", - Typez: genclient.BYTES_TYPE, + Typez: api.BYTES_TYPE, }, }, }) } func TestProtobuf_SkipExternalMessages(t *testing.T) { - api := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "with_import.proto")) - + test := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "with_import.proto")) // Both `ImportedMessage` and `LocalMessage` should be in the index: - _, ok := api.State.MessageByID[".away.ImportedMessage"] + _, ok := test.State.MessageByID[".away.ImportedMessage"] if !ok { t.Fatalf("Cannot find message %s in API State", ".away.ImportedMessage") } - message, ok := api.State.MessageByID[".test.LocalMessage"] + message, ok := test.State.MessageByID[".test.LocalMessage"] if !ok { t.Fatalf("Cannot find message %s in API State", ".test.LocalMessage") } @@ -284,13 +281,13 @@ func TestProtobuf_SkipExternalMessages(t *testing.T) { Package: "test", ID: ".test.LocalMessage", Documentation: "This is a local message, it should be generated.", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "payload", JSONName: "payload", ID: ".test.LocalMessage.payload", Documentation: "This field uses an imported message.", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".away.ImportedMessage", Optional: true, }, @@ -299,14 +296,14 @@ func TestProtobuf_SkipExternalMessages(t *testing.T) { JSONName: "value", ID: ".test.LocalMessage.value", Documentation: "This field uses an imported enum.", - Typez: genclient.ENUM_TYPE, + Typez: api.ENUM_TYPE, TypezID: ".away.ImportedEnum", Optional: false, }, }, }) // Only `LocalMessage` should be found in the messages list: - for _, msg := range api.Messages { + for _, msg := range test.Messages { if msg.ID == ".test.ImportedMessage" { t.Errorf("imported messages should not be in message list %v", msg) } @@ -314,14 +311,13 @@ func TestProtobuf_SkipExternalMessages(t *testing.T) { } func TestProtobuf_SkipExternaEnums(t *testing.T) { - api := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "with_import.proto")) - + test := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "with_import.proto")) // Both `ImportedEnum` and `LocalEnum` should be in the index: - _, ok := api.State.EnumByID[".away.ImportedEnum"] + _, ok := test.State.EnumByID[".away.ImportedEnum"] if !ok { t.Fatalf("Cannot find enum %s in API State", ".away.ImportedEnum") } - enum, ok := api.State.EnumByID[".test.LocalEnum"] + enum, ok := test.State.EnumByID[".test.LocalEnum"] if !ok { t.Fatalf("Cannot find enum %s in API State", ".test.LocalEnum") } @@ -329,7 +325,7 @@ func TestProtobuf_SkipExternaEnums(t *testing.T) { Name: "LocalEnum", Package: "test", Documentation: "This is a local enum, it should be generated.", - Values: []*genclient.EnumValue{ + Values: []*api.EnumValue{ { Name: "RED", Number: 0, @@ -345,7 +341,7 @@ func TestProtobuf_SkipExternaEnums(t *testing.T) { }, }) // Only `LocalMessage` should be found in the messages list: - for _, msg := range api.Messages { + for _, msg := range test.Messages { if msg.ID == ".test.ImportedMessage" { t.Errorf("imported messages should not be in message list %v", msg) } @@ -353,9 +349,8 @@ func TestProtobuf_SkipExternaEnums(t *testing.T) { } func TestProtobuf_Comments(t *testing.T) { - api := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "comments.proto")) - - message, ok := api.State.MessageByID[".test.Request"] + test := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "comments.proto")) + message, ok := test.State.MessageByID[".test.Request"] if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Request") } @@ -364,18 +359,18 @@ func TestProtobuf_Comments(t *testing.T) { Package: "test", ID: ".test.Request", Documentation: "A test message.\n\nWith even more of a description.\nMaybe in more than one line.\nAnd some markdown:\n- An item\n - A nested item\n- Another item", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "parent", Documentation: "A field.\n\nWith a longer description.", JSONName: "parent", ID: ".test.Request.parent", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, }, }, }) - message, ok = api.State.MessageByID[".test.Response.Nested"] + message, ok = test.State.MessageByID[".test.Response.Nested"] if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Response.nested") } @@ -384,18 +379,18 @@ func TestProtobuf_Comments(t *testing.T) { Package: "test", ID: ".test.Response.Nested", Documentation: "A nested message.\n\n- Item 1\n Item 1 continued", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "path", Documentation: "Field in a nested message.\n\n* Bullet 1\n Bullet 1 continued\n* Bullet 2\n Bullet 2 continued", JSONName: "path", ID: ".test.Response.Nested.path", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, }, }, }) - e, ok := api.State.EnumByID[".test.Response.Status"] + e, ok := test.State.EnumByID[".test.Response.Status"] if !ok { t.Fatalf("Cannot find enum %s in API State", ".test.Response.Status") } @@ -403,7 +398,7 @@ func TestProtobuf_Comments(t *testing.T) { Name: "Status", Package: "test", Documentation: "Some enum.\n\nLine 1.\nLine 2.", - Values: []*genclient.EnumValue{ + Values: []*api.EnumValue{ { Name: "NOT_READY", Documentation: "The first enum value description.\n\nValue Line 1.\nValue Line 2.", @@ -417,7 +412,7 @@ func TestProtobuf_Comments(t *testing.T) { }, }) - service, ok := api.State.ServiceByID[".test.Service"] + service, ok := test.State.ServiceByID[".test.Service"] if !ok { t.Fatalf("Cannot find service %s in API State", ".test.Service") } @@ -427,19 +422,19 @@ func TestProtobuf_Comments(t *testing.T) { Package: "test", Documentation: "A service.\n\nWith a longer service description.", DefaultHost: "test.googleapis.com", - Methods: []*genclient.Method{ + Methods: []*api.Method{ { Name: "Create", ID: ".test.Service.Create", Documentation: "Some RPC.\n\nIt does not do much.", InputTypeID: ".test.Request", OutputTypeID: ".test.Response", - PathInfo: &genclient.PathInfo{ + PathInfo: &api.PathInfo{ Verb: "POST", - PathTemplate: []genclient.PathSegment{ - genclient.NewLiteralPathSegment("v1"), - genclient.NewFieldPathPathSegment("parent"), - genclient.NewLiteralPathSegment("foos"), + PathTemplate: []api.PathSegment{ + api.NewLiteralPathSegment("v1"), + api.NewFieldPathPathSegment("parent"), + api.NewLiteralPathSegment("foos"), }, QueryParameters: map[string]bool{}, BodyFieldPath: "*", @@ -450,8 +445,8 @@ func TestProtobuf_Comments(t *testing.T) { } func TestProtobuf_OneOfs(t *testing.T) { - api := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "oneofs.proto")) - message, ok := api.State.MessageByID[".test.Fake"] + test := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "oneofs.proto")) + message, ok := test.State.MessageByID[".test.Fake"] if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Request") } @@ -460,20 +455,20 @@ func TestProtobuf_OneOfs(t *testing.T) { Package: "test", ID: ".test.Fake", Documentation: "A test message.", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "field_one", Documentation: "A string choice", JSONName: "fieldOne", ID: ".test.Fake.field_one", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, IsOneOf: true, }, { Documentation: "An int choice", Name: "field_two", ID: ".test.Fake.field_two", - Typez: genclient.INT64_TYPE, + Typez: api.INT64_TYPE, JSONName: "fieldTwo", IsOneOf: true, }, @@ -481,7 +476,7 @@ func TestProtobuf_OneOfs(t *testing.T) { Documentation: "Optional is oneof in proto", Name: "field_three", ID: ".test.Fake.field_three", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, JSONName: "fieldThree", Optional: true, }, @@ -489,15 +484,15 @@ func TestProtobuf_OneOfs(t *testing.T) { Documentation: "A normal field", Name: "field_four", ID: ".test.Fake.field_four", - Typez: genclient.INT32_TYPE, + Typez: api.INT32_TYPE, JSONName: "fieldFour", }, }, - OneOfs: []*genclient.OneOf{ + OneOfs: []*api.OneOf{ { Name: "choice", ID: ".test.Fake.choice", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Documentation: "A string choice", Name: "field_one", @@ -521,9 +516,8 @@ func TestProtobuf_OneOfs(t *testing.T) { } func TestProtobuf_ObjectFields(t *testing.T) { - api := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "object_fields.proto")) - - message, ok := api.State.MessageByID[".test.Fake"] + test := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "object_fields.proto")) + message, ok := test.State.MessageByID[".test.Fake"] if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Fake") } @@ -531,14 +525,14 @@ func TestProtobuf_ObjectFields(t *testing.T) { Name: "Fake", Package: "test", ID: ".test.Fake", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Repeated: false, Optional: true, Name: "singular_object", JSONName: "singularObject", ID: ".test.Fake.singular_object", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".test.Other", }, { @@ -547,7 +541,7 @@ func TestProtobuf_ObjectFields(t *testing.T) { Name: "repeated_object", JSONName: "repeatedObject", ID: ".test.Fake.repeated_object", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".test.Other", }, }, @@ -555,9 +549,8 @@ func TestProtobuf_ObjectFields(t *testing.T) { } func TestProtobuf_WellKnownTypeFields(t *testing.T) { - api := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "wkt_fields.proto")) - - message, ok := api.State.MessageByID[".test.Fake"] + test := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "wkt_fields.proto")) + message, ok := test.State.MessageByID[".test.Fake"] if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Fake") } @@ -565,12 +558,12 @@ func TestProtobuf_WellKnownTypeFields(t *testing.T) { Name: "Fake", Package: "test", ID: ".test.Fake", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Name: "field_mask", JSONName: "fieldMask", ID: ".test.Fake.field_mask", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.FieldMask", Optional: true, }, @@ -578,7 +571,7 @@ func TestProtobuf_WellKnownTypeFields(t *testing.T) { Name: "timestamp", JSONName: "timestamp", ID: ".test.Fake.timestamp", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.Timestamp", Optional: true, }, @@ -586,7 +579,7 @@ func TestProtobuf_WellKnownTypeFields(t *testing.T) { Name: "any", JSONName: "any", ID: ".test.Fake.any", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.Any", Optional: true, }, @@ -594,7 +587,7 @@ func TestProtobuf_WellKnownTypeFields(t *testing.T) { Name: "repeated_field_mask", JSONName: "repeatedFieldMask", ID: ".test.Fake.repeated_field_mask", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.FieldMask", Repeated: true, }, @@ -602,7 +595,7 @@ func TestProtobuf_WellKnownTypeFields(t *testing.T) { Name: "repeated_timestamp", JSONName: "repeatedTimestamp", ID: ".test.Fake.repeated_timestamp", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.Timestamp", Repeated: true, }, @@ -610,7 +603,7 @@ func TestProtobuf_WellKnownTypeFields(t *testing.T) { Name: "repeated_any", JSONName: "repeatedAny", ID: ".test.Fake.repeated_any", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".google.protobuf.Any", Repeated: true, }, @@ -619,9 +612,8 @@ func TestProtobuf_WellKnownTypeFields(t *testing.T) { } func TestProtobuf_MapFields(t *testing.T) { - api := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "map_fields.proto")) - - message, ok := api.State.MessageByID[".test.Fake"] + test := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "map_fields.proto")) + message, ok := test.State.MessageByID[".test.Fake"] if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Fake") } @@ -629,20 +621,20 @@ func TestProtobuf_MapFields(t *testing.T) { Name: "Fake", Package: "test", ID: ".test.Fake", - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Repeated: false, Optional: false, Name: "singular_map", JSONName: "singularMap", ID: ".test.Fake.singular_map", - Typez: genclient.MESSAGE_TYPE, + Typez: api.MESSAGE_TYPE, TypezID: ".test.Fake.SingularMapEntry", }, }, }) - message, ok = api.State.MessageByID[".test.Fake.SingularMapEntry"] + message, ok = test.State.MessageByID[".test.Fake.SingularMapEntry"] if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Fake") } @@ -651,14 +643,14 @@ func TestProtobuf_MapFields(t *testing.T) { Package: "test", ID: ".test.Fake.SingularMapEntry", IsMap: true, - Fields: []*genclient.Field{ + Fields: []*api.Field{ { Repeated: false, Optional: false, Name: "key", JSONName: "key", ID: ".test.Fake.SingularMapEntry.key", - Typez: genclient.STRING_TYPE, + Typez: api.STRING_TYPE, }, { Repeated: false, @@ -666,16 +658,15 @@ func TestProtobuf_MapFields(t *testing.T) { Name: "value", JSONName: "value", ID: ".test.Fake.SingularMapEntry.value", - Typez: genclient.INT32_TYPE, + Typez: api.INT32_TYPE, }, }, }) } func TestProtobuf_Service(t *testing.T) { - api := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "test_service.proto")) - - service, ok := api.State.ServiceByID[".test.TestService"] + test := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "test_service.proto")) + service, ok := test.State.ServiceByID[".test.TestService"] if !ok { t.Fatalf("Cannot find service %s in API State", ".test.TestService") } @@ -685,18 +676,18 @@ func TestProtobuf_Service(t *testing.T) { ID: ".test.TestService", Documentation: "A service to unit test the protobuf translator.", DefaultHost: "test.googleapis.com", - Methods: []*genclient.Method{ + Methods: []*api.Method{ { Name: "GetFoo", ID: ".test.TestService.GetFoo", Documentation: "Gets a Foo resource.", InputTypeID: ".test.GetFooRequest", OutputTypeID: ".test.Foo", - PathInfo: &genclient.PathInfo{ + PathInfo: &api.PathInfo{ Verb: "GET", - PathTemplate: []genclient.PathSegment{ - genclient.NewLiteralPathSegment("v1"), - genclient.NewFieldPathPathSegment("name"), + PathTemplate: []api.PathSegment{ + api.NewLiteralPathSegment("v1"), + api.NewFieldPathPathSegment("name"), }, QueryParameters: map[string]bool{}, BodyFieldPath: "", @@ -708,12 +699,12 @@ func TestProtobuf_Service(t *testing.T) { Documentation: "Creates a new Foo resource.", InputTypeID: ".test.CreateFooRequest", OutputTypeID: ".test.Foo", - PathInfo: &genclient.PathInfo{ + PathInfo: &api.PathInfo{ Verb: "POST", - PathTemplate: []genclient.PathSegment{ - genclient.NewLiteralPathSegment("v1"), - genclient.NewFieldPathPathSegment("parent"), - genclient.NewLiteralPathSegment("foos"), + PathTemplate: []api.PathSegment{ + api.NewLiteralPathSegment("v1"), + api.NewFieldPathPathSegment("parent"), + api.NewLiteralPathSegment("foos"), }, QueryParameters: map[string]bool{"foo_id": true}, BodyFieldPath: "foo", @@ -724,9 +715,8 @@ func TestProtobuf_Service(t *testing.T) { } func TestProtobuf_QueryParameters(t *testing.T) { - api := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "query_parameters.proto")) - - service, ok := api.State.ServiceByID[".test.TestService"] + test := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "query_parameters.proto")) + service, ok := test.State.ServiceByID[".test.TestService"] if !ok { t.Fatalf("Cannot find service %s in API State", ".test.TestService") } @@ -736,19 +726,19 @@ func TestProtobuf_QueryParameters(t *testing.T) { ID: ".test.TestService", Documentation: "A service to unit test the protobuf translator.", DefaultHost: "test.googleapis.com", - Methods: []*genclient.Method{ + Methods: []*api.Method{ { Name: "CreateFoo", ID: ".test.TestService.CreateFoo", Documentation: "Creates a new `Foo` resource. `Foo`s are containers for `Bar`s.\n\nShows how a `body: \"${field}\"` option works.", InputTypeID: ".test.CreateFooRequest", OutputTypeID: ".test.Foo", - PathInfo: &genclient.PathInfo{ + PathInfo: &api.PathInfo{ Verb: "POST", - PathTemplate: []genclient.PathSegment{ - genclient.NewLiteralPathSegment("v1"), - genclient.NewFieldPathPathSegment("parent"), - genclient.NewLiteralPathSegment("foos"), + PathTemplate: []api.PathSegment{ + api.NewLiteralPathSegment("v1"), + api.NewFieldPathPathSegment("parent"), + api.NewLiteralPathSegment("foos"), }, QueryParameters: map[string]bool{"foo_id": true}, BodyFieldPath: "bar", @@ -760,12 +750,12 @@ func TestProtobuf_QueryParameters(t *testing.T) { Documentation: "Add a Bar resource.\n\nShows how a `body: \"*\"` option works.", InputTypeID: ".test.AddBarRequest", OutputTypeID: ".test.Bar", - PathInfo: &genclient.PathInfo{ + PathInfo: &api.PathInfo{ Verb: "POST", - PathTemplate: []genclient.PathSegment{ - genclient.NewLiteralPathSegment("v1"), - genclient.NewFieldPathPathSegment("parent"), - genclient.NewVerbPathSegment("addFoo"), + PathTemplate: []api.PathSegment{ + api.NewLiteralPathSegment("v1"), + api.NewFieldPathPathSegment("parent"), + api.NewVerbPathSegment("addFoo"), }, QueryParameters: map[string]bool{}, BodyFieldPath: "*", @@ -776,8 +766,8 @@ func TestProtobuf_QueryParameters(t *testing.T) { } func TestProtobuf_Enum(t *testing.T) { - api := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "enum.proto")) - e, ok := api.State.EnumByID[".test.Code"] + test := makeAPIForProtobuf(nil, newTestCodeGeneratorRequest(t, "enum.proto")) + e, ok := test.State.EnumByID[".test.Code"] if !ok { t.Fatalf("Cannot find enum %s in API State", ".test.Code") } @@ -785,7 +775,7 @@ func TestProtobuf_Enum(t *testing.T) { Name: "Code", Package: "test", Documentation: "An enum.", - Values: []*genclient.EnumValue{ + Values: []*api.EnumValue{ { Name: "OK", Documentation: "Not an error; returned on success.", @@ -850,8 +840,8 @@ func TestProtobuf_LocationMixin(t *testing.T) { }, }, } - api := makeAPIForProtobuf(serviceConfig, newTestCodeGeneratorRequest(t, "test_service.proto")) - service, ok := api.State.ServiceByID[".google.cloud.location.Locations"] + test := makeAPIForProtobuf(serviceConfig, newTestCodeGeneratorRequest(t, "test_service.proto")) + service, ok := test.State.ServiceByID[".google.cloud.location.Locations"] if !ok { t.Fatalf("Cannot find service %s in API State", ".google.cloud.location.Locations") } @@ -861,18 +851,18 @@ func TestProtobuf_LocationMixin(t *testing.T) { Name: "Locations", ID: ".google.cloud.location.Locations", Package: "google.cloud.location", - Methods: []*genclient.Method{ + Methods: []*api.Method{ { Documentation: "GetLocation is an RPC method of Locations.", Name: "GetLocation", ID: ".google.cloud.location.Locations.GetLocation", InputTypeID: ".google.cloud.location.GetLocationRequest", OutputTypeID: ".google.cloud.location.Location", - PathInfo: &genclient.PathInfo{ + PathInfo: &api.PathInfo{ Verb: "GET", - PathTemplate: []genclient.PathSegment{ - genclient.NewLiteralPathSegment("v1"), - genclient.NewFieldPathPathSegment("name"), + PathTemplate: []api.PathSegment{ + api.NewLiteralPathSegment("v1"), + api.NewFieldPathPathSegment("name"), }, QueryParameters: map[string]bool{}, }, @@ -909,8 +899,8 @@ func TestProtobuf_IAMMixin(t *testing.T) { }, }, } - api := makeAPIForProtobuf(serviceConfig, newTestCodeGeneratorRequest(t, "test_service.proto")) - service, ok := api.State.ServiceByID[".google.iam.v1.IAMPolicy"] + test := makeAPIForProtobuf(serviceConfig, newTestCodeGeneratorRequest(t, "test_service.proto")) + service, ok := test.State.ServiceByID[".google.iam.v1.IAMPolicy"] if !ok { t.Fatalf("Cannot find service %s in API State", ".google.iam.v1.IAMPolicy") } @@ -920,19 +910,19 @@ func TestProtobuf_IAMMixin(t *testing.T) { Name: "IAMPolicy", ID: ".google.iam.v1.IAMPolicy", Package: "google.iam.v1", - Methods: []*genclient.Method{ + Methods: []*api.Method{ { Documentation: "GetIamPolicy is an RPC method of IAMPolicy.", Name: "GetIamPolicy", ID: ".google.iam.v1.IAMPolicy.GetIamPolicy", InputTypeID: ".google.iam.v1.GetIamPolicyRequest", OutputTypeID: ".google.iam.v1.Policy", - PathInfo: &genclient.PathInfo{ + PathInfo: &api.PathInfo{ Verb: "POST", - PathTemplate: []genclient.PathSegment{ - genclient.NewLiteralPathSegment("v1"), - genclient.NewFieldPathPathSegment("resource"), - genclient.NewVerbPathSegment("getIamPolicy"), + PathTemplate: []api.PathSegment{ + api.NewLiteralPathSegment("v1"), + api.NewFieldPathPathSegment("resource"), + api.NewVerbPathSegment("getIamPolicy"), }, QueryParameters: map[string]bool{}, BodyFieldPath: "*", @@ -976,8 +966,8 @@ func TestProtobuf_OperationMixin(t *testing.T) { }, }, } - api := makeAPIForProtobuf(serviceConfig, newTestCodeGeneratorRequest(t, "test_service.proto")) - service, ok := api.State.ServiceByID[".google.longrunning.Operations"] + test := makeAPIForProtobuf(serviceConfig, newTestCodeGeneratorRequest(t, "test_service.proto")) + service, ok := test.State.ServiceByID[".google.longrunning.Operations"] if !ok { t.Fatalf("Cannot find service %s in API State", ".google.longrunning.Operations") } @@ -987,18 +977,18 @@ func TestProtobuf_OperationMixin(t *testing.T) { Name: "Operations", ID: ".google.longrunning.Operations", Package: "google.longrunning", - Methods: []*genclient.Method{ + Methods: []*api.Method{ { Documentation: "Custom docs.", Name: "GetOperation", ID: ".google.longrunning.Operations.GetOperation", InputTypeID: ".google.longrunning.GetOperationRequest", OutputTypeID: ".google.longrunning.Operation", - PathInfo: &genclient.PathInfo{ + PathInfo: &api.PathInfo{ Verb: "GET", - PathTemplate: []genclient.PathSegment{ - genclient.NewLiteralPathSegment("v2"), - genclient.NewFieldPathPathSegment("name"), + PathTemplate: []api.PathSegment{ + api.NewLiteralPathSegment("v2"), + api.NewFieldPathPathSegment("name"), }, QueryParameters: map[string]bool{}, BodyFieldPath: "*", diff --git a/generator/internal/sidekick/refresh.go b/generator/internal/sidekick/refresh.go index 8cd8ccd2a..faa4a58ea 100644 --- a/generator/internal/sidekick/refresh.go +++ b/generator/internal/sidekick/refresh.go @@ -18,6 +18,7 @@ import ( "fmt" "path" + "github.com/googleapis/google-cloud-rust/generator/internal/api" "github.com/googleapis/google-cloud-rust/generator/internal/genclient" "github.com/googleapis/google-cloud-rust/generator/internal/language" "github.com/googleapis/google-cloud-rust/generator/internal/parser" @@ -44,12 +45,12 @@ func refresh(rootConfig *Config, cmdLine *CommandLine, output string) error { Options: config.Source, } - var api *genclient.API + var a *api.API switch specFormat { case "openapi": - api, err = parser.ParseOpenAPI(*popts) + a, err = parser.ParseOpenAPI(*popts) case "protobuf": - api, err = parser.ParseProtobuf(*popts) + a, err = parser.ParseProtobuf(*popts) default: return fmt.Errorf("unknown parser %q", specFormat) } @@ -58,7 +59,7 @@ func refresh(rootConfig *Config, cmdLine *CommandLine, output string) error { } var ( - codec genclient.LanguageCodec + codec api.LanguageCodec copts = &genclient.CodecOptions{ OutDir: output, Options: config.Codec, @@ -75,12 +76,12 @@ func refresh(rootConfig *Config, cmdLine *CommandLine, output string) error { if err != nil { return err } - if err := codec.Validate(api); err != nil { + if err := codec.Validate(a); err != nil { return err } request := &genclient.GenerateRequest{ - API: api, + API: a, Codec: codec, OutDir: output, TemplateDir: config.General.TemplateDir, From e4a1e178b7b68dc8774872a8fc77732f6bea18ea Mon Sep 17 00:00:00 2001 From: Julie Qiu Date: Sat, 30 Nov 2024 10:56:32 -0500 Subject: [PATCH 2/2] code review --- generator/internal/parser/openapi.go | 18 ++++----- generator/internal/parser/openapi_test.go | 8 ++-- generator/internal/parser/parser_test.go | 28 ++++++------- generator/internal/parser/protobuf.go | 24 +++++------ ...annotations.go => protobuf_annotations.go} | 2 - generator/internal/parser/protobuf_test.go | 40 +++++++++---------- 6 files changed, 59 insertions(+), 61 deletions(-) rename generator/internal/parser/{annotations.go => protobuf_annotations.go} (98%) diff --git a/generator/internal/parser/openapi.go b/generator/internal/parser/openapi.go index 47c3533dd..9d10cb7bd 100644 --- a/generator/internal/parser/openapi.go +++ b/generator/internal/parser/openapi.go @@ -64,7 +64,7 @@ func createDocModel(contents []byte) (*libopenapi.DocumentModel[v3.Document], er } func makeAPIForOpenAPI(serviceConfig *serviceconfig.Service, model *libopenapi.DocumentModel[v3.Document]) (*api.API, error) { - a := &api.API{ + result := &api.API{ Name: "", Title: model.Model.Info.Title, Description: model.Model.Info.Description, @@ -78,9 +78,9 @@ func makeAPIForOpenAPI(serviceConfig *serviceconfig.Service, model *libopenapi.D } if serviceConfig != nil { - a.Name = strings.TrimSuffix(serviceConfig.Name, ".googleapis.com") - a.Title = serviceConfig.Title - a.Description = serviceConfig.Documentation.Summary + result.Name = strings.TrimSuffix(serviceConfig.Name, ".googleapis.com") + result.Title = serviceConfig.Title + result.Description = serviceConfig.Documentation.Summary } // OpenAPI does not define a service name. The service config may provide @@ -103,7 +103,7 @@ func makeAPIForOpenAPI(serviceConfig *serviceconfig.Service, model *libopenapi.D if err != nil { return nil, err } - fields, err := makeMessageFields(a.State, packageName, name, schema) + fields, err := makeMessageFields(result.State, packageName, name, schema) if err != nil { return nil, err } @@ -115,15 +115,15 @@ func makeAPIForOpenAPI(serviceConfig *serviceconfig.Service, model *libopenapi.D Fields: fields, } - a.Messages = append(a.Messages, message) - a.State.MessageByID[id] = message + result.Messages = append(result.Messages, message) + result.State.MessageByID[id] = message } - err := makeServices(a, model, packageName, serviceName) + err := makeServices(result, model, packageName, serviceName) if err != nil { return nil, err } - return a, nil + return result, nil } func makeServices(a *api.API, model *libopenapi.DocumentModel[v3.Document], packageName, serviceName string) error { diff --git a/generator/internal/parser/openapi_test.go b/generator/internal/parser/openapi_test.go index b4b45c4eb..92d3531bd 100644 --- a/generator/internal/parser/openapi_test.go +++ b/generator/internal/parser/openapi_test.go @@ -373,7 +373,7 @@ func TestOpenAPI_SimpleObject(t *testing.T) { t.Fatalf("Error in makeAPI() %q", err) } - checkMessage(t, *api.Messages[0], api.Message{ + checkMessage(t, *test.Messages[0], api.Message{ Name: "Fake", ID: "..Fake", Documentation: "A test message.", @@ -420,7 +420,7 @@ func TestOpenAPI_Any(t *testing.T) { t.Errorf("Error in makeAPI() %q", err) } - checkMessage(t, *api.Messages[0], api.Message{ + checkMessage(t, *test.Messages[0], api.Message{ Name: "Fake", ID: "..Fake", Documentation: "A test message.", @@ -453,7 +453,7 @@ func TestOpenAPI_MapString(t *testing.T) { t.Fatal(err) } - checkMessage(t, *api.Messages[0], api.Message{ + checkMessage(t, *test.Messages[0], api.Message{ Name: "Fake", ID: "..Fake", Documentation: "A test message.", @@ -502,7 +502,7 @@ func TestOpenAPI_MapInteger(t *testing.T) { t.Errorf("Error in makeAPI() %q", err) } - checkMessage(t, *api.Messages[0], api.Message{ + checkMessage(t, *test.Messages[0], api.Message{ Name: "Fake", ID: "..Fake", Documentation: "A test message.", diff --git a/generator/internal/parser/parser_test.go b/generator/internal/parser/parser_test.go index c745b86cd..746d37d4a 100644 --- a/generator/internal/parser/parser_test.go +++ b/generator/internal/parser/parser_test.go @@ -19,50 +19,50 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/googleapis/google-cloud-rust/generator/internal/genclient" + "github.com/googleapis/google-cloud-rust/generator/internal/api" ) -func checkMessage(t *testing.T, got genclient.Message, want genclient.Message) { +func checkMessage(t *testing.T, got api.Message, want api.Message) { t.Helper() // Checking Parent, Messages, Fields, and OneOfs requires special handling. - if diff := cmp.Diff(want, got, cmpopts.IgnoreFields(genclient.Message{}, "Fields", "OneOfs", "Parent", "Messages")); diff != "" { + if diff := cmp.Diff(want, got, cmpopts.IgnoreFields(api.Message{}, "Fields", "OneOfs", "Parent", "Messages")); diff != "" { t.Errorf("message attributes mismatch (-want +got):\n%s", diff) } - less := func(a, b *genclient.Field) bool { return a.Name < b.Name } + less := func(a, b *api.Field) bool { return a.Name < b.Name } if diff := cmp.Diff(want.Fields, got.Fields, cmpopts.SortSlices(less)); diff != "" { t.Errorf("field mismatch (-want, +got):\n%s", diff) } // Ignore parent because types are cyclic - if diff := cmp.Diff(want.OneOfs, got.OneOfs, cmpopts.SortSlices(less), cmpopts.IgnoreFields(genclient.OneOf{}, "Parent")); diff != "" { + if diff := cmp.Diff(want.OneOfs, got.OneOfs, cmpopts.SortSlices(less), cmpopts.IgnoreFields(api.OneOf{}, "Parent")); diff != "" { t.Errorf("oneofs mismatch (-want, +got):\n%s", diff) } } -func checkEnum(t *testing.T, got genclient.Enum, want genclient.Enum) { +func checkEnum(t *testing.T, got api.Enum, want api.Enum) { t.Helper() - if diff := cmp.Diff(want, got, cmpopts.IgnoreFields(genclient.Enum{}, "Values", "Parent")); diff != "" { + if diff := cmp.Diff(want, got, cmpopts.IgnoreFields(api.Enum{}, "Values", "Parent")); diff != "" { t.Errorf("mismatched service attributes (-want, +got):\n%s", diff) } - less := func(a, b *genclient.EnumValue) bool { return a.Name < b.Name } - if diff := cmp.Diff(want.Values, got.Values, cmpopts.SortSlices(less), cmpopts.IgnoreFields(genclient.EnumValue{}, "Parent")); diff != "" { + less := func(a, b *api.EnumValue) bool { return a.Name < b.Name } + if diff := cmp.Diff(want.Values, got.Values, cmpopts.SortSlices(less), cmpopts.IgnoreFields(api.EnumValue{}, "Parent")); diff != "" { t.Errorf("method mismatch (-want, +got):\n%s", diff) } } -func checkService(t *testing.T, got genclient.Service, want genclient.Service) { +func checkService(t *testing.T, got api.Service, want api.Service) { t.Helper() - if diff := cmp.Diff(want, got, cmpopts.IgnoreFields(genclient.Service{}, "Methods")); diff != "" { + if diff := cmp.Diff(want, got, cmpopts.IgnoreFields(api.Service{}, "Methods")); diff != "" { t.Errorf("mismatched service attributes (-want, +got):\n%s", diff) } - less := func(a, b *genclient.Method) bool { return a.Name < b.Name } + less := func(a, b *api.Method) bool { return a.Name < b.Name } if diff := cmp.Diff(want.Methods, got.Methods, cmpopts.SortSlices(less)); diff != "" { t.Errorf("method mismatch (-want, +got):\n%s", diff) } } -func checkMethod(t *testing.T, service *genclient.Service, name string, want *genclient.Method) { +func checkMethod(t *testing.T, service *api.Service, name string, want *api.Method) { t.Helper() - findMethod := func(name string) (*genclient.Method, bool) { + findMethod := func(name string) (*api.Method, bool) { for _, method := range service.Methods { if method.Name == name { return method, true diff --git a/generator/internal/parser/protobuf.go b/generator/internal/parser/protobuf.go index d1a4b494d..9409517e1 100644 --- a/generator/internal/parser/protobuf.go +++ b/generator/internal/parser/protobuf.go @@ -218,12 +218,12 @@ func makeAPIForProtobuf(serviceConfig *serviceconfig.Service, req *pluginpb.Code MessageByID: make(map[string]*api.Message), EnumByID: make(map[string]*api.Enum), } - a := &api.API{ + result := &api.API{ State: state, } if serviceConfig != nil { - a.Title = serviceConfig.Title - a.Description = serviceConfig.Documentation.Summary + result.Title = serviceConfig.Title + result.Description = serviceConfig.Documentation.Summary enabledMixinMethods, mixinFileDesc = loadMixins(serviceConfig) packageName := "" for _, api := range serviceConfig.Apis { @@ -233,7 +233,7 @@ func makeAPIForProtobuf(serviceConfig *serviceconfig.Service, req *pluginpb.Code break } } - a.PackageName = packageName + result.PackageName = packageName } // First we need to add all the message and enums types to the @@ -263,7 +263,7 @@ func makeAPIForProtobuf(serviceConfig *serviceconfig.Service, req *pluginpb.Code for _, m := range f.MessageType { mFQN := fFQN + "." + m.GetName() if msg, ok := state.MessageByID[mFQN]; ok { - a.Messages = append(a.Messages, msg) + result.Messages = append(result.Messages, msg) } else { slog.Warn("missing message in symbol table", "message", mFQN) } @@ -273,7 +273,7 @@ func makeAPIForProtobuf(serviceConfig *serviceconfig.Service, req *pluginpb.Code for _, e := range f.EnumType { eFQN := fFQN + "." + e.GetName() if e, ok := state.EnumByID[eFQN]; ok { - a.Enums = append(a.Enums, e) + result.Enums = append(result.Enums, e) } else { slog.Warn("missing enum in symbol table", "message", eFQN) } @@ -315,7 +315,7 @@ func makeAPIForProtobuf(serviceConfig *serviceconfig.Service, req *pluginpb.Code slog.Warn("file dropped documentation", "loc", p, "docs", loc.GetLeadingComments()) } } - a.Services = append(a.Services, fileServices...) + result.Services = append(result.Services, fileServices...) } // Handle mixins @@ -336,13 +336,13 @@ func makeAPIForProtobuf(serviceConfig *serviceconfig.Service, req *pluginpb.Code } fileServices = append(fileServices, service) } - a.Services = append(a.Services, fileServices...) + result.Services = append(result.Services, fileServices...) } - updateMixinState(serviceConfig, a) - if a.Name == "" && serviceConfig != nil { - a.Name = strings.TrimSuffix(serviceConfig.Name, ".googleapis.com") + updateMixinState(serviceConfig, result) + if result.Name == "" && serviceConfig != nil { + result.Name = strings.TrimSuffix(serviceConfig.Name, ".googleapis.com") } - return a + return result } var descriptorpbToTypez = map[descriptorpb.FieldDescriptorProto_Type]api.Typez{ diff --git a/generator/internal/parser/annotations.go b/generator/internal/parser/protobuf_annotations.go similarity index 98% rename from generator/internal/parser/annotations.go rename to generator/internal/parser/protobuf_annotations.go index 654f661cc..bec18c7bd 100644 --- a/generator/internal/parser/annotations.go +++ b/generator/internal/parser/protobuf_annotations.go @@ -130,5 +130,3 @@ func parseDefaultHost(m proto.Message) string { } return defaultHost } - -// TODO(codyoss): https://github.com/googleapis/google-cloud-rust/issues/27 diff --git a/generator/internal/parser/protobuf_test.go b/generator/internal/parser/protobuf_test.go index 4658d0775..dc4824b12 100644 --- a/generator/internal/parser/protobuf_test.go +++ b/generator/internal/parser/protobuf_test.go @@ -54,7 +54,7 @@ func TestProtobuf_Scalar(t *testing.T) { if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Fake") } - checkMessage(t, *message, genclient.Message{ + checkMessage(t, *message, api.Message{ Name: "Fake", Package: "test", ID: ".test.Fake", @@ -175,7 +175,7 @@ func TestProtobuf_ScalarArray(t *testing.T) { if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Fake") } - checkMessage(t, *message, genclient.Message{ + checkMessage(t, *message, api.Message{ Name: "Fake", Package: "test", ID: ".test.Fake", @@ -223,7 +223,7 @@ func TestProtobuf_ScalarOptional(t *testing.T) { if !ok { t.Fatalf("Cannot find message %s in API", "Fake") } - checkMessage(t, *message, genclient.Message{ + checkMessage(t, *message, api.Message{ Name: "Fake", Package: "test", ID: ".test.Fake", @@ -276,7 +276,7 @@ func TestProtobuf_SkipExternalMessages(t *testing.T) { if !ok { t.Fatalf("Cannot find message %s in API State", ".test.LocalMessage") } - checkMessage(t, *message, genclient.Message{ + checkMessage(t, *message, api.Message{ Name: "LocalMessage", Package: "test", ID: ".test.LocalMessage", @@ -321,7 +321,7 @@ func TestProtobuf_SkipExternaEnums(t *testing.T) { if !ok { t.Fatalf("Cannot find enum %s in API State", ".test.LocalEnum") } - checkEnum(t, *enum, genclient.Enum{ + checkEnum(t, *enum, api.Enum{ Name: "LocalEnum", Package: "test", Documentation: "This is a local enum, it should be generated.", @@ -354,7 +354,7 @@ func TestProtobuf_Comments(t *testing.T) { if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Request") } - checkMessage(t, *message, genclient.Message{ + checkMessage(t, *message, api.Message{ Name: "Request", Package: "test", ID: ".test.Request", @@ -374,7 +374,7 @@ func TestProtobuf_Comments(t *testing.T) { if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Response.nested") } - checkMessage(t, *message, genclient.Message{ + checkMessage(t, *message, api.Message{ Name: "Nested", Package: "test", ID: ".test.Response.Nested", @@ -394,7 +394,7 @@ func TestProtobuf_Comments(t *testing.T) { if !ok { t.Fatalf("Cannot find enum %s in API State", ".test.Response.Status") } - checkEnum(t, *e, genclient.Enum{ + checkEnum(t, *e, api.Enum{ Name: "Status", Package: "test", Documentation: "Some enum.\n\nLine 1.\nLine 2.", @@ -416,7 +416,7 @@ func TestProtobuf_Comments(t *testing.T) { if !ok { t.Fatalf("Cannot find service %s in API State", ".test.Service") } - checkService(t, *service, genclient.Service{ + checkService(t, *service, api.Service{ Name: "Service", ID: ".test.Service", Package: "test", @@ -450,7 +450,7 @@ func TestProtobuf_OneOfs(t *testing.T) { if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Request") } - checkMessage(t, *message, genclient.Message{ + checkMessage(t, *message, api.Message{ Name: "Fake", Package: "test", ID: ".test.Fake", @@ -521,7 +521,7 @@ func TestProtobuf_ObjectFields(t *testing.T) { if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Fake") } - checkMessage(t, *message, genclient.Message{ + checkMessage(t, *message, api.Message{ Name: "Fake", Package: "test", ID: ".test.Fake", @@ -554,7 +554,7 @@ func TestProtobuf_WellKnownTypeFields(t *testing.T) { if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Fake") } - checkMessage(t, *message, genclient.Message{ + checkMessage(t, *message, api.Message{ Name: "Fake", Package: "test", ID: ".test.Fake", @@ -617,7 +617,7 @@ func TestProtobuf_MapFields(t *testing.T) { if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Fake") } - checkMessage(t, *message, genclient.Message{ + checkMessage(t, *message, api.Message{ Name: "Fake", Package: "test", ID: ".test.Fake", @@ -638,7 +638,7 @@ func TestProtobuf_MapFields(t *testing.T) { if !ok { t.Fatalf("Cannot find message %s in API State", ".test.Fake") } - checkMessage(t, *message, genclient.Message{ + checkMessage(t, *message, api.Message{ Name: "SingularMapEntry", Package: "test", ID: ".test.Fake.SingularMapEntry", @@ -670,7 +670,7 @@ func TestProtobuf_Service(t *testing.T) { if !ok { t.Fatalf("Cannot find service %s in API State", ".test.TestService") } - checkService(t, *service, genclient.Service{ + checkService(t, *service, api.Service{ Name: "TestService", Package: "test", ID: ".test.TestService", @@ -720,7 +720,7 @@ func TestProtobuf_QueryParameters(t *testing.T) { if !ok { t.Fatalf("Cannot find service %s in API State", ".test.TestService") } - checkService(t, *service, genclient.Service{ + checkService(t, *service, api.Service{ Name: "TestService", Package: "test", ID: ".test.TestService", @@ -771,7 +771,7 @@ func TestProtobuf_Enum(t *testing.T) { if !ok { t.Fatalf("Cannot find enum %s in API State", ".test.Code") } - checkEnum(t, *e, genclient.Enum{ + checkEnum(t, *e, api.Enum{ Name: "Code", Package: "test", Documentation: "An enum.", @@ -845,7 +845,7 @@ func TestProtobuf_LocationMixin(t *testing.T) { if !ok { t.Fatalf("Cannot find service %s in API State", ".google.cloud.location.Locations") } - checkService(t, *service, genclient.Service{ + checkService(t, *service, api.Service{ Documentation: "Manages location-related information with an API service.", DefaultHost: "cloud.googleapis.com", Name: "Locations", @@ -904,7 +904,7 @@ func TestProtobuf_IAMMixin(t *testing.T) { if !ok { t.Fatalf("Cannot find service %s in API State", ".google.iam.v1.IAMPolicy") } - checkService(t, *service, genclient.Service{ + checkService(t, *service, api.Service{ Documentation: "Manages Identity and Access Management (IAM) policies with an API service.", DefaultHost: "iam-meta-api.googleapis.com", Name: "IAMPolicy", @@ -971,7 +971,7 @@ func TestProtobuf_OperationMixin(t *testing.T) { if !ok { t.Fatalf("Cannot find service %s in API State", ".google.longrunning.Operations") } - checkService(t, *service, genclient.Service{ + checkService(t, *service, api.Service{ Documentation: "Manages long-running operations with an API service.", DefaultHost: "longrunning.googleapis.com", Name: "Operations",