Skip to content

Commit

Permalink
fix: nested messages
Browse files Browse the repository at this point in the history
Example

```proto
message ListItemOp {
  message Create {
    string name = 1;
  }
}

message Item {
  repeated ListItemOp.Create items = 1;
}
```
  • Loading branch information
askuzminov committed Mar 22, 2021
1 parent 4330100 commit 1207457
Show file tree
Hide file tree
Showing 14 changed files with 403 additions and 29 deletions.
11 changes: 9 additions & 2 deletions proto/whisk/api/user/v2/user.proto
Original file line number Diff line number Diff line change
Expand Up @@ -236,14 +236,17 @@ message TestEmpty {
}

message SearchRecipesResponse {
message MatchedIngredient { string name = 1; }
message MatchedIngredient {
string name = 1;
message Recommendations { int32 daily_calories = 1; }
}

message Empty {}

message Hit {
MatchedIngredient content = 1 [ deprecated = true ];
repeated MatchedIngredient ingredients = 2 [ required = true ];
map<string, MatchedIngredient> map_ingredients = 3;
map<string, MatchedIngredient.Recommendations> map_ingredients = 3;
map<string, TestItem> map_external = 4;
}

Expand All @@ -253,6 +256,10 @@ message SearchRecipesResponse {
Empty empty = 4;
}

message DeepCheck {
repeated SearchRecipesResponse.Hit items = 1;
}

message ApiUpdateBusinessApp {
string id = 1;
TestItem app_any = 2;
Expand Down
26 changes: 16 additions & 10 deletions src/generator/field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,39 @@ export const getField = (
} else if (isString(TYPES[GOOGLE_WRAPPERS[type]])) {
return TYPES[GOOGLE_WRAPPERS[type]];
} else {
const sName = pathField(type, base);
const sName = pathField(type, base, out);
out.fields.push([sName, name]);
return enumsList.has(sName) ? `${sName}` : sName;
}
};

export const getStruct = (field: Parser.Field, base: string, enumsList: EnumsList): string => {
export const getStruct = (field: Parser.Field, base: string, enumsList: EnumsList, out: MakeOuts): string => {
const type = field.type;

if (type === 'map') {
const from = getStruct({ type: field.map?.from } as Parser.Field, base, enumsList);
const to = getStruct({ type: field.map?.to } as Parser.Field, base, enumsList);
const from = getStruct({ type: field.map?.from } as Parser.Field, base, enumsList, out);
const to = getStruct({ type: field.map?.to } as Parser.Field, base, enumsList, out);
return `["map", ${from}, ${to}]`;
} else if (field.repeated) {
return `["repeated", ${getStruct({ type } as Parser.Field, base, enumsList)}]`;
return `["repeated", ${getStruct({ type } as Parser.Field, base, enumsList, out)}]`;
} else if (isString(TYPES[type])) {
return `"${type}"`;
} else if (isString(GOOGLE_WRAPPERS[type])) {
return `["wrapper", "${GOOGLE_WRAPPERS[type]}"]`;
} else {
const sName = pathField(field.type, base);
const sName = pathField(field.type, base, out);
return enumsList.has(sName) ? '"enum"' : sName;
}
};

export const pathField = (field: string, base: string) =>
/\./.test(field) ? safeString(field) : safeString(`${base}_${field}`);
export const pathField = (field: string, base: string, out: MakeOuts) => {
let inRoot = false;
out.roots.forEach(root => {
inRoot = inRoot || field.startsWith(root);
});

return inRoot ? safeString(field) : safeString(`${base}_${field}`);
};

export const isRequiredField = (field: Parser.Field) =>
isPresent(field.options.required)
Expand All @@ -58,5 +64,5 @@ export const isRequiredField = (field: Parser.Field) =>
? false
: field.required || field.repeated || field.type === 'map' || isString(TYPES[field.type]);

export const isEnumField = (field: Parser.Field, base: string, enumsList: EnumsList) =>
enumsList.has(pathField(field.type, base));
export const isEnumField = (field: Parser.Field, base: string, enumsList: EnumsList, out: MakeOuts) =>
enumsList.has(pathField(field.type, base, out));
1 change: 1 addition & 0 deletions src/generator/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export type MakeOuts = {
names: Set<string>;
fields: [string, string][];
errors: string[];
roots: Set<string>;
};

export type List = { name: string; pack: string };
Expand Down
6 changes: 6 additions & 0 deletions src/generator/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,14 @@ export function make(schemas: Parser.Schema[]): MakeOuts {
names: new Set(),
errors: [],
fields: [],
roots: new Set(),
};

for (const schema of schemas) {
const path = schema.package ?? '';
out.roots.add(path);
}

for (const schema of schemas) {
const path = schema.package ?? '';
enums(path, out, schema.enums, enumsList);
Expand Down
2 changes: 1 addition & 1 deletion src/generator/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function message(
out.dts.push(` ${naming}${required ? '' : '?'}: ${fieldName}${field.repeated ? '[]' : ''};`);
}

const type = getStruct(field, fieldPack, enumsList);
const type = getStruct(field, fieldPack, enumsList, out);
runtime.push(
` [${field.tag}, "${naming}", ${type}, ${required ? '1' : '0'}${
isText(field.oneof) ? `, "${field.oneof}"` : ''
Expand Down
4 changes: 2 additions & 2 deletions src/generator/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ function service(pack: string, out: MakeOuts, item: Parser.Service) {

export function method(pack: string, out: MakeOuts, item: Parser.Method, serv: Parser.Service) {
const sName = `${safeString(pack)}_${serv.name}_${item.name}`;
const input = pathField(item.inputType, pack);
const output = pathField(item.outputType, pack);
const input = pathField(item.inputType, pack, out);
const output = pathField(item.outputType, pack, out);

checkDublicate(sName, out, `${pack}.${serv.name}.${item.name}`);
out.fields.push([input, sName], [output, sName]);
Expand Down
45 changes: 43 additions & 2 deletions tests/proto/debug/whisk/api/user/v2/user.json
Original file line number Diff line number Diff line change
Expand Up @@ -1296,7 +1296,28 @@
"name": "MatchedIngredient",
"enums": [],
"options": {},
"messages": [],
"messages": [
{
"name": "Recommendations",
"enums": [],
"options": {},
"messages": [],
"fields": [
{
"name": "daily_calories",
"type": "int32",
"tag": 1,
"required": false,
"repeated": false,
"optional": false,
"options": {}
}
],
"extends": [],
"extensions": [],
"reserved": []
}
],
"fields": [
{
"name": "name",
Expand Down Expand Up @@ -1360,7 +1381,7 @@
"options": {},
"map": {
"from": "string",
"to": "MatchedIngredient"
"to": "MatchedIngredient.Recommendations"
}
},
{
Expand Down Expand Up @@ -1424,6 +1445,26 @@
"extensions": [],
"reserved": []
},
{
"name": "DeepCheck",
"enums": [],
"options": {},
"messages": [],
"fields": [
{
"name": "items",
"type": "SearchRecipesResponse.Hit",
"tag": 1,
"required": false,
"repeated": true,
"optional": false,
"options": {}
}
],
"extends": [],
"extensions": [],
"reserved": []
},
{
"name": "ApiUpdateBusinessApp",
"enums": [],
Expand Down
12 changes: 11 additions & 1 deletion tests/proto/esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -856,17 +856,27 @@ export function whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient() {
[1, "name", "string", 1],
];
}
export function whisk_api_user_v2_MatchedIngredient_Recommendations() {
return [
[1, "dailyCalories", "int32", 1],
];
}
export function whisk_api_user_v2_SearchRecipesResponse_Empty() {
return [];
}
export function whisk_api_user_v2_SearchRecipesResponse_Hit() {
return [
[1, "content", whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient, 0],
[2, "ingredients", ["repeated", whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient], 1],
[3, "mapIngredients", ["map", "string", whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient], 1],
[3, "mapIngredients", ["map", "string", whisk_api_user_v2_MatchedIngredient_Recommendations], 1],
[4, "mapExternal", ["map", "string", whisk_api_user_v2_TestItem], 1],
];
}
export function whisk_api_user_v2_DeepCheck() {
return [
[1, "items", ["repeated", whisk_api_user_v2_SearchRecipesResponse_Hit], 1],
];
}
export function whisk_api_user_v2_ApiUpdateBusinessApp() {
return [
[1, "id", "string", 1],
Expand Down
10 changes: 9 additions & 1 deletion tests/proto/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -804,16 +804,24 @@ export type whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient = {
name: string;
};
export const whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient: Field<whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient>;
export type whisk_api_user_v2_MatchedIngredient_Recommendations = {
dailyCalories: number;
};
export const whisk_api_user_v2_MatchedIngredient_Recommendations: Field<whisk_api_user_v2_MatchedIngredient_Recommendations>;
export type whisk_api_user_v2_SearchRecipesResponse_Empty = FieldEmpty;
export const whisk_api_user_v2_SearchRecipesResponse_Empty: Field<whisk_api_user_v2_SearchRecipesResponse_Empty>;
export type whisk_api_user_v2_SearchRecipesResponse_Hit = {
/** @deprecated */
content?: whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient;
ingredients: whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient[];
mapIngredients: Record<string, whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient>;
mapIngredients: Record<string, whisk_api_user_v2_MatchedIngredient_Recommendations>;
mapExternal: Record<string, whisk_api_user_v2_TestItem>;
};
export const whisk_api_user_v2_SearchRecipesResponse_Hit: Field<whisk_api_user_v2_SearchRecipesResponse_Hit>;
export type whisk_api_user_v2_DeepCheck = {
items: whisk_api_user_v2_SearchRecipesResponse_Hit[];
};
export const whisk_api_user_v2_DeepCheck: Field<whisk_api_user_v2_DeepCheck>;
export type whisk_api_user_v2_ApiUpdateBusinessApp = {
id: string;
appAny?: whisk_api_user_v2_TestItem;
Expand Down
16 changes: 14 additions & 2 deletions tests/proto/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.google_protobuf_GeneratedCodeInfo_Annotation = exports.google_protobuf_GeneratedCodeInfo = exports.google_protobuf_SourceCodeInfo_Location = exports.google_protobuf_SourceCodeInfo = exports.google_protobuf_UninterpretedOption_NamePart = exports.google_protobuf_UninterpretedOption = exports.google_protobuf_MethodOptions = exports.google_protobuf_MethodOptions_IdempotencyLevel = exports.google_protobuf_ServiceOptions = exports.google_protobuf_EnumValueOptions = exports.google_protobuf_EnumOptions = exports.google_protobuf_OneofOptions = exports.google_protobuf_FieldOptions = exports.google_protobuf_FieldOptions_JSType = exports.google_protobuf_FieldOptions_CType = exports.google_protobuf_MessageOptions = exports.google_protobuf_FileOptions = exports.google_protobuf_FileOptions_OptimizeMode = exports.google_protobuf_MethodDescriptorProto = exports.google_protobuf_ServiceDescriptorProto = exports.google_protobuf_EnumValueDescriptorProto = exports.google_protobuf_EnumDescriptorProto_EnumReservedRange = exports.google_protobuf_EnumDescriptorProto = exports.google_protobuf_OneofDescriptorProto = exports.google_protobuf_FieldDescriptorProto = exports.google_protobuf_FieldDescriptorProto_Label = exports.google_protobuf_FieldDescriptorProto_Type = exports.google_protobuf_ExtensionRangeOptions = exports.google_protobuf_DescriptorProto_ReservedRange = exports.google_protobuf_DescriptorProto_ExtensionRange = exports.google_protobuf_DescriptorProto = exports.google_protobuf_FileDescriptorProto = exports.google_protobuf_FileDescriptorSet = exports.google_protobuf_Mixin = exports.google_protobuf_Method = exports.google_protobuf_Api = exports.google_protobuf_Any = exports.google_api_HttpBody = exports.google_api_CustomHttpPattern = exports.google_api_HttpRule = exports.google_api_Http = exports.whisk_api_user_v2_EthicalPreference = exports.whisk_api_user_v2_BudgetGoal = exports.whisk_api_user_v2_CookingExperience = exports.whisk_api_user_v2_OrganicPreference = exports.whisk_api_user_v2_Gender = exports.whisk_api_user_v2_ActivityLevel = exports.whisk_api_user_v2_HealthGoal = exports.google_protobuf_Syntax = exports.google_protobuf_NullValue = void 0;
exports.whisk_api_user_v2_CookingPreferences_CookingMaxTime = exports.whisk_api_user_v2_CookingPreferences_HouseholdMembers = exports.whisk_api_user_v2_CookingPreferences = exports.whisk_api_user_v2_FoodPreferences_Ingredients = exports.whisk_api_user_v2_FoodPreferences_Dates = exports.whisk_api_user_v2_FoodPreferences = exports.whisk_api_user_v2_Weight = exports.whisk_api_user_v2_Weight_Unit = exports.whisk_api_user_v2_Height = exports.whisk_api_user_v2_Height_Unit = exports.whisk_api_user_v2_PersonalDetails_HealthGoals = exports.whisk_api_user_v2_PersonalDetails = exports.whisk_api_user_v2_UserSettings = exports.whisk_api_user_v2_User = exports.whisk_api_shared_v1_Wrapper = exports.whisk_api_shared_v1_Double = exports.whisk_api_shared_v1_Sign = exports.whisk_api_shared_v1_Big = exports.whisk_api_shared_v1_Primitive = exports.whisk_api_shared_v1_Time = exports.whisk_api_shared_v1_Date = exports.whisk_api_shared_v1_Outer = exports.whisk_api_shared_v1_Inner_InnerInner = exports.whisk_api_shared_v1_Test_Inner = exports.whisk_api_shared_v1_Test = exports.whisk_api_shared_v1_Test_Enum = exports.google_protobuf_BytesValue = exports.google_protobuf_StringValue = exports.google_protobuf_BoolValue = exports.google_protobuf_UInt32Value = exports.google_protobuf_Int32Value = exports.google_protobuf_UInt64Value = exports.google_protobuf_Int64Value = exports.google_protobuf_FloatValue = exports.google_protobuf_DoubleValue = exports.google_protobuf_Option = exports.google_protobuf_EnumValue = exports.google_protobuf_Enum = exports.google_protobuf_Field = exports.google_protobuf_Field_Cardinality = exports.google_protobuf_Field_Kind = exports.google_protobuf_Type = exports.google_protobuf_Timestamp = exports.google_protobuf_ListValue = exports.google_protobuf_Value = exports.google_protobuf_Struct = exports.google_protobuf_SourceContext = exports.google_protobuf_FieldMask = exports.google_protobuf_Empty = exports.google_protobuf_Duration = void 0;
exports.whisk_api_user_v2_UserAPI_UpdateSettings = exports.whisk_api_user_v2_UserAPI_Get = exports.whisk_api_user_v2_UserAPI_GetMe = exports.whisk_api_user_v2_UserSettings2 = exports.whisk_api_user_v2_UpdateBusinessApp = exports.whisk_api_user_v2_UpdateSettingsRequestOld = exports.whisk_api_user_v2_UpdateItemRequest_Fields = exports.whisk_api_user_v2_UpdateItemRequest = exports.whisk_api_user_v2_UpdateListRequest_Fields = exports.whisk_api_user_v2_UpdateListRequest = exports.whisk_api_user_v2_UpdateRecipeRequest = exports.whisk_api_user_v2_SaveRecipeRequest = exports.whisk_api_user_v2_ExtractRecipeRequest = exports.whisk_api_user_v2_UpdateSettingsResponse = exports.whisk_api_user_v2_UpdateSettingsRequest = exports.whisk_api_user_v2_GetMeResponse = exports.whisk_api_user_v2_GetMeRequest = exports.whisk_api_user_v2_ApiUpdateBusinessApp = exports.whisk_api_user_v2_SearchRecipesResponse_Hit = exports.whisk_api_user_v2_SearchRecipesResponse_Empty = exports.whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient = exports.whisk_api_user_v2_SearchRecipesResponse = exports.whisk_api_user_v2_TestEmpty_GlobalRegion = exports.whisk_api_user_v2_TestEmpty = exports.whisk_api_user_v2_TestOneof = exports.whisk_api_user_v2_TestItem = exports.whisk_api_user_v2_Recommendations = exports.whisk_api_user_v2_Ingredient = exports.whisk_api_user_v2_ShoppingPreferences_EthicalPreferences = exports.whisk_api_user_v2_ShoppingPreferences_PreferredRetailers = exports.whisk_api_user_v2_ShoppingPreferences = exports.whisk_api_user_v2_Device = exports.whisk_api_user_v2_Device_DeviceType = exports.whisk_api_user_v2_CookingPreferences_Devices = void 0;
exports.whisk_api_user_v2_UserAPI_UpdateSettings = exports.whisk_api_user_v2_UserAPI_Get = exports.whisk_api_user_v2_UserAPI_GetMe = exports.whisk_api_user_v2_UserSettings2 = exports.whisk_api_user_v2_UpdateBusinessApp = exports.whisk_api_user_v2_UpdateSettingsRequestOld = exports.whisk_api_user_v2_UpdateItemRequest_Fields = exports.whisk_api_user_v2_UpdateItemRequest = exports.whisk_api_user_v2_UpdateListRequest_Fields = exports.whisk_api_user_v2_UpdateListRequest = exports.whisk_api_user_v2_UpdateRecipeRequest = exports.whisk_api_user_v2_SaveRecipeRequest = exports.whisk_api_user_v2_ExtractRecipeRequest = exports.whisk_api_user_v2_UpdateSettingsResponse = exports.whisk_api_user_v2_UpdateSettingsRequest = exports.whisk_api_user_v2_GetMeResponse = exports.whisk_api_user_v2_GetMeRequest = exports.whisk_api_user_v2_ApiUpdateBusinessApp = exports.whisk_api_user_v2_DeepCheck = exports.whisk_api_user_v2_SearchRecipesResponse_Hit = exports.whisk_api_user_v2_SearchRecipesResponse_Empty = exports.whisk_api_user_v2_MatchedIngredient_Recommendations = exports.whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient = exports.whisk_api_user_v2_SearchRecipesResponse = exports.whisk_api_user_v2_TestEmpty_GlobalRegion = exports.whisk_api_user_v2_TestEmpty = exports.whisk_api_user_v2_TestOneof = exports.whisk_api_user_v2_TestItem = exports.whisk_api_user_v2_Recommendations = exports.whisk_api_user_v2_Ingredient = exports.whisk_api_user_v2_ShoppingPreferences_EthicalPreferences = exports.whisk_api_user_v2_ShoppingPreferences_PreferredRetailers = exports.whisk_api_user_v2_ShoppingPreferences = exports.whisk_api_user_v2_Device = exports.whisk_api_user_v2_Device_DeviceType = exports.whisk_api_user_v2_CookingPreferences_Devices = void 0;
exports.google_protobuf_NullValue = {
NULL_VALUE: 0,
};
Expand Down Expand Up @@ -953,6 +953,12 @@ function whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient() {
];
}
exports.whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient = whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient;
function whisk_api_user_v2_MatchedIngredient_Recommendations() {
return [
[1, "dailyCalories", "int32", 1],
];
}
exports.whisk_api_user_v2_MatchedIngredient_Recommendations = whisk_api_user_v2_MatchedIngredient_Recommendations;
function whisk_api_user_v2_SearchRecipesResponse_Empty() {
return [];
}
Expand All @@ -961,11 +967,17 @@ function whisk_api_user_v2_SearchRecipesResponse_Hit() {
return [
[1, "content", whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient, 0],
[2, "ingredients", ["repeated", whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient], 1],
[3, "mapIngredients", ["map", "string", whisk_api_user_v2_SearchRecipesResponse_MatchedIngredient], 1],
[3, "mapIngredients", ["map", "string", whisk_api_user_v2_MatchedIngredient_Recommendations], 1],
[4, "mapExternal", ["map", "string", whisk_api_user_v2_TestItem], 1],
];
}
exports.whisk_api_user_v2_SearchRecipesResponse_Hit = whisk_api_user_v2_SearchRecipesResponse_Hit;
function whisk_api_user_v2_DeepCheck() {
return [
[1, "items", ["repeated", whisk_api_user_v2_SearchRecipesResponse_Hit], 1],
];
}
exports.whisk_api_user_v2_DeepCheck = whisk_api_user_v2_DeepCheck;
function whisk_api_user_v2_ApiUpdateBusinessApp() {
return [
[1, "id", "string", 1],
Expand Down
21 changes: 20 additions & 1 deletion tests/protobufjs/json-module.js
Original file line number Diff line number Diff line change
Expand Up @@ -1900,6 +1900,16 @@ const $root = ($protobuf.roots["default"] || ($protobuf.roots["default"] = new $
type: "string",
id: 1
}
},
nested: {
Recommendations: {
fields: {
dailyCalories: {
type: "int32",
id: 1
}
}
}
}
},
Empty: {
Expand All @@ -1924,7 +1934,7 @@ const $root = ($protobuf.roots["default"] || ($protobuf.roots["default"] = new $
},
mapIngredients: {
keyType: "string",
type: "MatchedIngredient",
type: "MatchedIngredient.Recommendations",
id: 3
},
mapExternal: {
Expand All @@ -1936,6 +1946,15 @@ const $root = ($protobuf.roots["default"] || ($protobuf.roots["default"] = new $
}
}
},
DeepCheck: {
fields: {
items: {
rule: "repeated",
type: "SearchRecipesResponse.Hit",
id: 1
}
}
},
ApiUpdateBusinessApp: {
fields: {
id: {
Expand Down

0 comments on commit 1207457

Please sign in to comment.