-
Notifications
You must be signed in to change notification settings - Fork 343
/
visit.ts
80 lines (71 loc) · 2.76 KB
/
visit.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import {
DescriptorProto,
EnumDescriptorProto,
FileDescriptorProto,
ServiceDescriptorProto,
} from "ts-proto-descriptors";
import SourceInfo, { Fields } from "./sourceInfo";
import { Options } from "./options";
import { maybeSnakeToCamel } from "./case";
type MessageVisitor = (
fullName: string,
desc: DescriptorProto,
sourceInfo: SourceInfo,
fullProtoTypeName: string,
) => void;
type EnumVisitor = (
fullName: string,
desc: EnumDescriptorProto,
sourceInfo: SourceInfo,
fullProtoTypeName: string,
) => void;
export function visit(
proto: FileDescriptorProto | DescriptorProto,
sourceInfo: SourceInfo,
messageFn: MessageVisitor,
options: Options,
enumFn: EnumVisitor = () => {},
tsPrefix: string = "",
protoPrefix: string = "",
): void {
const isRootFile = "syntax" in proto;
const childEnumType = isRootFile ? Fields.file.enum_type : Fields.message.enum_type;
proto.enumType.forEach((enumDesc, index) => {
// I.e. Foo_Bar.Zaz_Inner
const protoFullName = protoPrefix + enumDesc.name;
// I.e. FooBar_ZazInner
const tsFullName = tsPrefix + maybeSnakeToCamel(enumDesc.name, options);
const tsFullNameWithAffixes = `${options.typePrefix}${tsFullName}${options.typeSuffix}`;
const nestedSourceInfo = sourceInfo.open(childEnumType, index);
enumFn(tsFullNameWithAffixes, enumDesc, nestedSourceInfo, protoFullName);
});
const messages = "messageType" in proto ? proto.messageType : proto.nestedType;
const childType = isRootFile ? Fields.file.message_type : Fields.message.nested_type;
messages.forEach((message, index) => {
// I.e. Foo_Bar.Zaz_Inner
const protoFullName = protoPrefix + message.name;
// I.e. FooBar_ZazInner
const tsFullName = tsPrefix + maybeSnakeToCamel(messageName(message), options);
const tsFullNameWithAffixes = `${options.typePrefix}${tsFullName}${options.typeSuffix}`;
const nestedSourceInfo = sourceInfo.open(childType, index);
messageFn(tsFullNameWithAffixes, message, nestedSourceInfo, protoFullName);
const delim = options.useSnakeTypeName ? "_" : "";
visit(message, nestedSourceInfo, messageFn, options, enumFn, tsFullName + delim, protoFullName + ".");
});
}
const builtInNames = ["Date"];
/** Potentially suffixes `Message` to names to avoid conflicts, i.e. with `Date`. */
function messageName(message: DescriptorProto): string {
const { name } = message;
return builtInNames.includes(name) ? `${name}Message` : name;
}
export function visitServices(
proto: FileDescriptorProto,
sourceInfo: SourceInfo,
serviceFn: (desc: ServiceDescriptorProto, sourceInfo: SourceInfo) => void,
): void {
proto.service.forEach((serviceDesc, index) => {
const nestedSourceInfo = sourceInfo.open(Fields.file.service, index);
serviceFn(serviceDesc, nestedSourceInfo);
});
}