Skip to content

Commit da69195

Browse files
authored
feat(sidekick): discovery doc arrays (#2337)
1 parent 1358226 commit da69195

File tree

2 files changed

+125
-57
lines changed

2 files changed

+125
-57
lines changed

internal/sidekick/internal/parser/discovery/message_fields.go

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ func makeMessageFields(model *api.API, messageID string, schema *schema) ([]*api
3737

3838
func makeField(model *api.API, messageID string, input *property) (*api.Field, error) {
3939
if input.Schema.Type == "array" {
40-
// TODO(#2266) - handle array fields
41-
return nil, nil
40+
return makeArrayField(model, messageID, input)
4241
}
4342
if input.Schema.AdditionalProperties != nil {
4443
// TODO(#2283) - handle map fields
@@ -51,8 +50,28 @@ func makeField(model *api.API, messageID string, input *property) (*api.Field, e
5150
return makeScalarField(model, messageID, input)
5251
}
5352

53+
func makeArrayField(model *api.API, messageID string, input *property) (*api.Field, error) {
54+
if input.Schema.ItemSchema.Type == "object" && input.Schema.ItemSchema.Properties != nil {
55+
// TODO(#2265) - handle inline object...
56+
return nil, nil
57+
}
58+
typez, typezID, err := scalarType(model, messageID, input.Name, input.Schema.ItemSchema)
59+
if err != nil {
60+
return nil, err
61+
}
62+
return &api.Field{
63+
Name: input.Name,
64+
JSONName: input.Name, // OpenAPI field names are always camelCase
65+
Documentation: input.Schema.Description,
66+
Typez: typez,
67+
TypezID: typezID,
68+
Repeated: true,
69+
// TODO(#2268) - deprecated fields?
70+
}, nil
71+
}
72+
5473
func makeScalarField(model *api.API, messageID string, input *property) (*api.Field, error) {
55-
typez, typezID, err := scalarType(model, messageID, input)
74+
typez, typezID, err := scalarType(model, messageID, input.Name, input.Schema)
5675
if err != nil {
5776
return nil, err
5877
}
@@ -68,30 +87,30 @@ func makeScalarField(model *api.API, messageID string, input *property) (*api.Fi
6887
}, nil
6988
}
7089

71-
func scalarType(model *api.API, messageID string, input *property) (api.Typez, string, error) {
72-
if input.Schema.Type == "" && input.Schema.Ref != "" {
73-
typezID := fmt.Sprintf(".%s.%s", model.PackageName, input.Schema.Ref)
90+
func scalarType(model *api.API, messageID, name string, input *schema) (api.Typez, string, error) {
91+
if input.Type == "" && input.Ref != "" {
92+
typezID := fmt.Sprintf(".%s.%s", model.PackageName, input.Ref)
7493
return api.MESSAGE_TYPE, typezID, nil
7594
}
76-
switch input.Schema.Type {
95+
switch input.Type {
7796
case "boolean":
7897
return api.BOOL_TYPE, "bool", nil
7998
case "integer":
80-
return scalarTypeForIntegerFormats(messageID, input)
99+
return scalarTypeForIntegerFormats(messageID, name, input)
81100
case "number":
82-
return scalarTypeForNumberFormats(messageID, input)
101+
return scalarTypeForNumberFormats(messageID, name, input)
83102
case "string":
84-
return scalarTypeForStringFormats(messageID, input)
103+
return scalarTypeForStringFormats(messageID, name, input)
85104
case "any":
86-
return scalarTypeForAny(messageID, input)
105+
return scalarTypeForAny(messageID, name, input)
87106
case "object":
88-
return scalarTypeForObject(messageID, input)
107+
return scalarTypeForObject(messageID, name, input)
89108
}
90-
return unknownFormat("scalar", messageID, input)
109+
return unknownFormat("scalar", messageID, name, input)
91110
}
92111

93-
func scalarTypeForIntegerFormats(messageID string, input *property) (api.Typez, string, error) {
94-
switch input.Schema.Format {
112+
func scalarTypeForIntegerFormats(messageID, name string, input *schema) (api.Typez, string, error) {
113+
switch input.Format {
95114
case "int32":
96115
return api.INT32_TYPE, "int32", nil
97116
case "uint32":
@@ -101,21 +120,21 @@ func scalarTypeForIntegerFormats(messageID string, input *property) (api.Typez,
101120
case "uint64":
102121
return api.UINT64_TYPE, "uint64", nil
103122
}
104-
return unknownFormat("integer", messageID, input)
123+
return unknownFormat("integer", messageID, name, input)
105124
}
106125

107-
func scalarTypeForNumberFormats(messageID string, input *property) (api.Typez, string, error) {
108-
switch input.Schema.Format {
126+
func scalarTypeForNumberFormats(messageID, name string, input *schema) (api.Typez, string, error) {
127+
switch input.Format {
109128
case "float":
110129
return api.FLOAT_TYPE, "float", nil
111130
case "double":
112131
return api.DOUBLE_TYPE, "double", nil
113132
}
114-
return unknownFormat("number", messageID, input)
133+
return unknownFormat("number", messageID, name, input)
115134
}
116135

117-
func scalarTypeForStringFormats(messageID string, input *property) (api.Typez, string, error) {
118-
switch input.Schema.Format {
136+
func scalarTypeForStringFormats(messageID, name string, input *schema) (api.Typez, string, error) {
137+
switch input.Format {
119138
case "":
120139
return api.STRING_TYPE, "string", nil
121140
case "byte":
@@ -133,27 +152,27 @@ func scalarTypeForStringFormats(messageID string, input *property) (api.Typez, s
133152
case "uint64":
134153
return api.UINT64_TYPE, "uint64", nil
135154
}
136-
return unknownFormat("string", messageID, input)
155+
return unknownFormat("string", messageID, name, input)
137156
}
138157

139-
func scalarTypeForAny(messageID string, input *property) (api.Typez, string, error) {
140-
switch input.Schema.Format {
158+
func scalarTypeForAny(messageID, name string, input *schema) (api.Typez, string, error) {
159+
switch input.Format {
141160
case "google.protobuf.Value":
142161
return api.MESSAGE_TYPE, ".google.protobuf.Value", nil
143162
}
144-
return unknownFormat("any", messageID, input)
163+
return unknownFormat("any", messageID, name, input)
145164
}
146165

147-
func scalarTypeForObject(messageID string, input *property) (api.Typez, string, error) {
148-
switch input.Schema.Format {
166+
func scalarTypeForObject(messageID, name string, input *schema) (api.Typez, string, error) {
167+
switch input.Format {
149168
case "google.protobuf.Struct":
150169
return api.MESSAGE_TYPE, ".google.protobuf.Struct", nil
151170
case "google.protobuf.Any":
152171
return api.MESSAGE_TYPE, ".google.protobuf.Any", nil
153172
}
154-
return unknownFormat("object", messageID, input)
173+
return unknownFormat("object", messageID, name, input)
155174
}
156175

157-
func unknownFormat(baseType, messageID string, input *property) (api.Typez, string, error) {
158-
return 0, "", fmt.Errorf("unknown %s format (%s) for field %s.%s", baseType, input.Schema.Format, messageID, input.Name)
176+
func unknownFormat(baseType, messageID, name string, input *schema) (api.Typez, string, error) {
177+
return 0, "", fmt.Errorf("unknown %s format (%s) for field %s.%s", baseType, input.Format, messageID, name)
159178
}

internal/sidekick/internal/parser/discovery/message_fields_test.go

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
func TestMakeMessageFields(t *testing.T) {
2626
model := api.NewTestAPI([]*api.Message{}, []*api.Enum{}, []*api.Service{})
27+
model.PackageName = "package"
2728
input := &schema{
2829
Properties: []*property{
2930
{
@@ -44,6 +45,28 @@ func TestMakeMessageFields(t *testing.T) {
4445
Format: "int32",
4546
},
4647
},
48+
{
49+
Name: "arrayFieldString",
50+
Schema: &schema{
51+
ID: ".package.Message.arrayFieldString",
52+
Description: "The field description.",
53+
Type: "array",
54+
ItemSchema: &schema{
55+
Type: "string",
56+
},
57+
},
58+
},
59+
{
60+
Name: "arrayFieldObject",
61+
Schema: &schema{
62+
ID: ".package.Message.arrayFieldObject",
63+
Description: "The field description.",
64+
Type: "array",
65+
ItemSchema: &schema{
66+
Ref: "AnotherMessage",
67+
},
68+
},
69+
},
4770
},
4871
}
4972
got, err := makeMessageFields(model, ".package.Message", input)
@@ -65,6 +88,22 @@ func TestMakeMessageFields(t *testing.T) {
6588
Typez: api.UINT64_TYPE,
6689
TypezID: "uint64",
6790
},
91+
{
92+
Name: "arrayFieldString",
93+
JSONName: "arrayFieldString",
94+
Documentation: "The field description.",
95+
Typez: api.STRING_TYPE,
96+
TypezID: "string",
97+
Repeated: true,
98+
},
99+
{
100+
Name: "arrayFieldObject",
101+
JSONName: "arrayFieldObject",
102+
Documentation: "The field description.",
103+
Typez: api.MESSAGE_TYPE,
104+
TypezID: ".package.AnotherMessage",
105+
Repeated: true,
106+
},
68107
}
69108
less := func(a, b *api.Field) bool { return a.Name < b.Name }
70109
if diff := cmp.Diff(want, got, cmpopts.SortSlices(less)); diff != "" {
@@ -92,6 +131,25 @@ func TestMakeMessageFieldsError(t *testing.T) {
92131
}
93132
}
94133

134+
func TestMakeArrayFieldError(t *testing.T) {
135+
model := api.NewTestAPI([]*api.Message{}, []*api.Enum{}, []*api.Service{})
136+
input := &property{
137+
Name: "field",
138+
Schema: &schema{
139+
Type: "array",
140+
ItemSchema: &schema{
141+
ID: ".package.Message.field",
142+
Description: "The field description.",
143+
Type: "--invalid--",
144+
Format: "--unused--",
145+
},
146+
},
147+
}
148+
if got, err := makeArrayField(model, ".package.Message", input); err == nil {
149+
t.Errorf("expected error makeScalarField(), got=%v, Input=%v", got, input)
150+
}
151+
}
152+
95153
func TestMakeScalarFieldError(t *testing.T) {
96154
model := api.NewTestAPI([]*api.Message{}, []*api.Enum{}, []*api.Service{})
97155
input := &property{
@@ -136,16 +194,13 @@ func TestScalarTypes(t *testing.T) {
136194
{"object", "google.protobuf.Any", api.MESSAGE_TYPE, ".google.protobuf.Any"},
137195
} {
138196
model := api.NewTestAPI([]*api.Message{}, []*api.Enum{}, []*api.Service{})
139-
input := &property{
140-
Name: "field",
141-
Schema: &schema{
142-
ID: ".package.Message.field",
143-
Description: "The field description.",
144-
Type: test.Type,
145-
Format: test.Format,
146-
},
197+
input := &schema{
198+
ID: ".package.Message.field",
199+
Description: "The field description.",
200+
Type: test.Type,
201+
Format: test.Format,
147202
}
148-
gotTypez, gotTypeID, err := scalarType(model, ".package.Message", input)
203+
gotTypez, gotTypeID, err := scalarType(model, ".package.Message", "field", input)
149204
if err != nil {
150205
t.Errorf("error in scalarType(), Type=%q, Format=%q: %v", test.Type, test.Format, err)
151206
}
@@ -162,16 +217,13 @@ func TestScalarTypes(t *testing.T) {
162217

163218
func TestScalarUnknownType(t *testing.T) {
164219
model := api.NewTestAPI([]*api.Message{}, []*api.Enum{}, []*api.Service{})
165-
input := &property{
166-
Name: "field",
167-
Schema: &schema{
168-
ID: ".package.Message.field",
169-
Description: "The field description.",
170-
Type: "--invalid--",
171-
Format: "--unused--",
172-
},
220+
input := &schema{
221+
ID: ".package.Message.field",
222+
Description: "The field description.",
223+
Type: "--invalid--",
224+
Format: "--unused--",
173225
}
174-
if gotTypez, gotTypeID, err := scalarType(model, ".package.Message", input); err == nil {
226+
if gotTypez, gotTypeID, err := scalarType(model, ".package.Message", "field", input); err == nil {
175227
t.Errorf("expected error scalarType(), gotTypez=%d, gotTypezID=%q, Input=%v", gotTypez, gotTypeID, input)
176228
}
177229
}
@@ -187,16 +239,13 @@ func TestScalarUnknownFormats(t *testing.T) {
187239
{"any"},
188240
{"object"},
189241
} {
190-
input := &property{
191-
Name: "field",
192-
Schema: &schema{
193-
ID: ".package.Message.field",
194-
Description: "The field description.",
195-
Type: test.Type,
196-
Format: "--invalid--",
197-
},
242+
input := &schema{
243+
ID: ".package.Message.field",
244+
Description: "The field description.",
245+
Type: test.Type,
246+
Format: "--invalid--",
198247
}
199-
if gotTypez, gotTypeID, err := scalarType(model, ".package.Message", input); err == nil {
248+
if gotTypez, gotTypeID, err := scalarType(model, ".package.Message", "field", input); err == nil {
200249
t.Errorf("expected error scalarType(), gotTypez=%d, gotTypezID=%q, Input=%v", gotTypez, gotTypeID, input)
201250
}
202251
}

0 commit comments

Comments
 (0)