@typespec/protobuf 0.49.0-dev.2 → 0.49.0-dev.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.rush/temp/package-deps_build.json +29 -27
- package/.rush/temp/shrinkwrap-deps.json +41 -38
- package/dist/src/ast.d.ts +29 -8
- package/dist/src/ast.d.ts.map +1 -1
- package/dist/src/ast.js.map +1 -1
- package/dist/src/transform/index.d.ts.map +1 -1
- package/dist/src/transform/index.js +13 -2
- package/dist/src/transform/index.js.map +1 -1
- package/dist/src/write.d.ts +0 -6
- package/dist/src/write.d.ts.map +1 -1
- package/dist/src/write.js +63 -30
- package/dist/src/write.js.map +1 -1
- package/lib/proto.tsp +5 -0
- package/package.json +4 -4
- package/src/ast.ts +33 -8
- package/src/transform/index.ts +17 -1
- package/src/write.ts +81 -30
- package/temp/tsconfig.tsbuildinfo +1 -1
- package/test/scenarios/addressbook/output/@typespec/protobuf/addressbook.proto +1 -1
- package/test/scenarios/addressbook/output/@typespec/protobuf/main.proto +1 -1
- package/test/scenarios/anonymous-package/output/@typespec/protobuf/main.proto +1 -1
- package/test/scenarios/array/output/@typespec/protobuf/com/azure/test.proto +1 -1
- package/test/scenarios/cross package references/output/@typespec/protobuf/A.proto +1 -1
- package/test/scenarios/cross package references/output/@typespec/protobuf/B.proto +1 -1
- package/test/scenarios/derived-scalar/output/@typespec/protobuf/com/azure/Test.proto +1 -1
- package/test/scenarios/doc/input/main.tsp +67 -0
- package/test/scenarios/doc/output/@typespec/protobuf/com/azure/Test.proto +35 -0
- package/test/scenarios/empty/output/@typespec/protobuf/main.proto +1 -1
- package/test/scenarios/enum/output/@typespec/protobuf/main.proto +1 -1
- package/test/scenarios/extern/output/@typespec/protobuf/main.proto +1 -1
- package/test/scenarios/inferred-message-names/output/@typespec/protobuf/com/azure/test.proto +1 -1
- package/test/scenarios/intrinsics/output/@typespec/protobuf/com/azure/Test.proto +1 -1
- package/test/scenarios/map/output/@typespec/protobuf/main.proto +1 -1
- package/test/scenarios/name-collision/output/@typespec/protobuf/main.proto +1 -1
- package/test/scenarios/omit/output/@typespec/protobuf/main.proto +1 -1
- package/test/scenarios/omit-off/output/@typespec/protobuf/main.proto +1 -1
- package/test/scenarios/options/output/@typespec/protobuf/com/azure/Test.proto +1 -1
- package/test/scenarios/reserved fields/output/@typespec/protobuf/main.proto +1 -1
- package/test/scenarios/simple/output/@typespec/protobuf/com/azure/Test.proto +1 -1
- package/test/scenarios/simple-no-service/output/@typespec/protobuf/com/azure/Test.proto +1 -1
- package/test/scenarios/streams/output/@typespec/protobuf/main.proto +1 -1
- package/.rush/temp/operation/build/all.log +0 -1
- package/.rush/temp/operation/build/state.json +0 -3
package/src/write.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
matchType,
|
|
6
6
|
ProtoDeclaration,
|
|
7
7
|
ProtoEnumDeclaration,
|
|
8
|
+
ProtoEnumVariantDeclaration,
|
|
8
9
|
ProtoFieldDeclaration,
|
|
9
10
|
ProtoFile,
|
|
10
11
|
ProtoMessageDeclaration,
|
|
@@ -17,21 +18,19 @@ import {
|
|
|
17
18
|
|
|
18
19
|
// This module defines how to emit the text representation of a ProtoFile AST.
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
* Header for the top of all emitted proto files.
|
|
22
|
-
*
|
|
23
|
-
* We only support Protobuf 3 syntax.
|
|
24
|
-
*/
|
|
25
|
-
export const PROTO_HEADER = `/* Generated by Microsoft TypeSpec */
|
|
26
|
-
|
|
27
|
-
syntax = "proto3";
|
|
28
|
-
`;
|
|
21
|
+
const PROTO_MAX_ONE_LINE_DOC_LENGTH = 80;
|
|
29
22
|
|
|
30
23
|
/**
|
|
31
24
|
* Write the given `file` to a string.
|
|
32
25
|
*/
|
|
33
26
|
export function writeProtoFile(file: ProtoFile): string {
|
|
34
|
-
let result =
|
|
27
|
+
let result = "// Generated by Microsoft TypeSpec\n";
|
|
28
|
+
|
|
29
|
+
let docComment = collect(writeBlockDocumentationComment(file)).join("\n");
|
|
30
|
+
if (docComment.length > 0) docComment = "\n" + docComment;
|
|
31
|
+
result += docComment;
|
|
32
|
+
|
|
33
|
+
result += '\nsyntax = "proto3";\n';
|
|
35
34
|
|
|
36
35
|
if (file.package) result += `\npackage ${file.package};\n`;
|
|
37
36
|
|
|
@@ -51,7 +50,7 @@ export function writeProtoFile(file: ProtoFile): string {
|
|
|
51
50
|
if (opts.length > 0) result += "\n";
|
|
52
51
|
|
|
53
52
|
for (const decl of file.declarations) {
|
|
54
|
-
result += "\n" + collect(writeDeclaration(decl)).join("\n") + "\n";
|
|
53
|
+
result += "\n" + collect(writeDeclaration(decl, 0)).join("\n") + "\n";
|
|
55
54
|
}
|
|
56
55
|
|
|
57
56
|
return result;
|
|
@@ -60,25 +59,28 @@ export function writeProtoFile(file: ProtoFile): string {
|
|
|
60
59
|
/**
|
|
61
60
|
* Write the given `decl` to a line iterable.
|
|
62
61
|
*/
|
|
63
|
-
function* writeDeclaration(decl: ProtoDeclaration): Iterable<string> {
|
|
62
|
+
function* writeDeclaration(decl: ProtoDeclaration, indentLevel: number): Iterable<string> {
|
|
64
63
|
switch (decl.kind) {
|
|
65
64
|
case "message":
|
|
66
|
-
yield* writeMessage(decl);
|
|
65
|
+
yield* writeMessage(decl, indentLevel);
|
|
67
66
|
return;
|
|
68
67
|
case "service":
|
|
69
|
-
yield* writeService(decl);
|
|
68
|
+
yield* writeService(decl, indentLevel);
|
|
70
69
|
return;
|
|
71
70
|
case "field":
|
|
72
|
-
yield writeField(decl);
|
|
71
|
+
yield* writeField(decl, indentLevel);
|
|
73
72
|
return;
|
|
74
73
|
case "oneof":
|
|
75
|
-
yield* writeOneOf(decl);
|
|
74
|
+
yield* writeOneOf(decl, indentLevel);
|
|
76
75
|
return;
|
|
77
76
|
case "enum":
|
|
78
|
-
yield* writeEnum(decl);
|
|
77
|
+
yield* writeEnum(decl, indentLevel);
|
|
78
|
+
return;
|
|
79
|
+
case "variant":
|
|
80
|
+
yield* writeVariant(decl, indentLevel);
|
|
79
81
|
return;
|
|
80
82
|
case "method":
|
|
81
|
-
yield writeMethod(decl);
|
|
83
|
+
yield* writeMethod(decl);
|
|
82
84
|
return;
|
|
83
85
|
/* c8 ignore next 5 */
|
|
84
86
|
default:
|
|
@@ -90,14 +92,16 @@ function* writeDeclaration(decl: ProtoDeclaration): Iterable<string> {
|
|
|
90
92
|
/**
|
|
91
93
|
* Write the given message `decl` to a line iterable.
|
|
92
94
|
*/
|
|
93
|
-
function* writeMessage(decl: ProtoMessageDeclaration): Iterable<string> {
|
|
95
|
+
function* writeMessage(decl: ProtoMessageDeclaration, indentLevel: number): Iterable<string> {
|
|
96
|
+
yield* writeBlockDocumentationComment(decl);
|
|
97
|
+
|
|
94
98
|
const head = `message ${decl.name} {`;
|
|
95
99
|
const tail = "}";
|
|
96
100
|
|
|
97
101
|
if (decl.declarations.length > 0 || decl.reservations?.length) {
|
|
98
102
|
yield head;
|
|
99
103
|
yield* indent(writeReservations(decl));
|
|
100
|
-
yield* indent(flatMap(decl.declarations, writeDeclaration));
|
|
104
|
+
yield* indent(flatMap(decl.declarations, (decl) => writeDeclaration(decl, indentLevel + 1)));
|
|
101
105
|
yield tail;
|
|
102
106
|
} else yield head + tail;
|
|
103
107
|
}
|
|
@@ -119,49 +123,65 @@ function* writeReservations(decl: ProtoMessageDeclaration): Iterable<string> {
|
|
|
119
123
|
}
|
|
120
124
|
}
|
|
121
125
|
|
|
122
|
-
function* writeService(decl: ProtoServiceDeclaration): Iterable<string> {
|
|
126
|
+
function* writeService(decl: ProtoServiceDeclaration, indentLevel: number): Iterable<string> {
|
|
127
|
+
yield* writeBlockDocumentationComment(decl);
|
|
128
|
+
|
|
123
129
|
const head = `service ${decl.name} {`;
|
|
124
130
|
const tail = "}";
|
|
125
131
|
|
|
126
132
|
if (decl.operations.length > 0) {
|
|
127
133
|
yield head;
|
|
128
|
-
yield* indent(flatMap(decl.operations, writeDeclaration));
|
|
134
|
+
yield* indent(flatMap(decl.operations, (decl) => writeDeclaration(decl, indentLevel + 1)));
|
|
129
135
|
yield tail;
|
|
130
136
|
} else yield head + tail;
|
|
131
137
|
}
|
|
132
138
|
|
|
133
|
-
function writeMethod(decl: ProtoMethodDeclaration): string {
|
|
139
|
+
function* writeMethod(decl: ProtoMethodDeclaration): Iterable<string> {
|
|
140
|
+
yield* writeBlockDocumentationComment(decl);
|
|
141
|
+
|
|
134
142
|
const [inStream, outStream] = [
|
|
135
143
|
decl.stream & StreamingMode.In,
|
|
136
144
|
decl.stream & StreamingMode.Out,
|
|
137
145
|
].map((v) => (v ? "stream " : ""));
|
|
138
146
|
|
|
139
|
-
|
|
147
|
+
yield `rpc ${decl.name}(${inStream}${writeType(decl.input)}) returns (${outStream}${writeType(
|
|
140
148
|
decl.returns
|
|
141
149
|
)});`;
|
|
142
150
|
}
|
|
143
151
|
|
|
144
|
-
function* writeOneOf(decl: ProtoOneOfDeclaration): Iterable<string> {
|
|
152
|
+
function* writeOneOf(decl: ProtoOneOfDeclaration, indentLevel: number): Iterable<string> {
|
|
153
|
+
yield* writeBlockDocumentationComment(decl);
|
|
154
|
+
|
|
145
155
|
// OneOf declarations must have at least one element, so no need to check for declarations
|
|
146
156
|
yield `oneof ${decl.name} {`;
|
|
147
|
-
yield* indent(flatMap(decl.declarations, writeDeclaration));
|
|
157
|
+
yield* indent(flatMap(decl.declarations, (decl) => writeDeclaration(decl, indentLevel + 1)));
|
|
148
158
|
yield "}";
|
|
149
159
|
}
|
|
150
160
|
|
|
151
|
-
function* writeEnum(decl: ProtoEnumDeclaration): Iterable<string> {
|
|
161
|
+
function* writeEnum(decl: ProtoEnumDeclaration, indentLevel: number): Iterable<string> {
|
|
162
|
+
yield* writeBlockDocumentationComment(decl);
|
|
163
|
+
|
|
152
164
|
yield `enum ${decl.name} {`;
|
|
153
165
|
if (decl.allowAlias) {
|
|
154
166
|
yield " option allow_alias = true;";
|
|
155
167
|
|
|
156
168
|
if (decl.variants.length > 0) yield "";
|
|
157
169
|
}
|
|
158
|
-
yield* indent(flatMap(decl.variants, (
|
|
170
|
+
yield* indent(flatMap(decl.variants, (decl) => writeDeclaration(decl, indentLevel + 1)));
|
|
159
171
|
yield "}";
|
|
160
172
|
}
|
|
161
173
|
|
|
162
|
-
function
|
|
174
|
+
function writeVariant(decl: ProtoEnumVariantDeclaration, indentLevel: number): Iterable<string> {
|
|
175
|
+
const output = `${decl.name} = ${decl.value};`;
|
|
176
|
+
|
|
177
|
+
return writeDocumentationCommentFlexible(decl, output, indentLevel);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function writeField(decl: ProtoFieldDeclaration, indentLevel: number): Iterable<string> {
|
|
163
181
|
const prefix = decl.repeated ? "repeated " : "";
|
|
164
|
-
|
|
182
|
+
const output = prefix + `${writeType(decl.type)} ${decl.name} = ${decl.index};`;
|
|
183
|
+
|
|
184
|
+
return writeDocumentationCommentFlexible(decl, output, indentLevel);
|
|
165
185
|
}
|
|
166
186
|
|
|
167
187
|
function writeType(type: ProtoType): string {
|
|
@@ -189,6 +209,37 @@ function* indent(it: Iterable<string>, depth: number = 2): Iterable<string> {
|
|
|
189
209
|
}
|
|
190
210
|
}
|
|
191
211
|
|
|
212
|
+
/**
|
|
213
|
+
* Writes a block comment from the given declaration.
|
|
214
|
+
*/
|
|
215
|
+
function* writeBlockDocumentationComment(decl: ProtoDeclaration | ProtoFile): Iterable<string> {
|
|
216
|
+
yield* decl.doc
|
|
217
|
+
?.trim()
|
|
218
|
+
.split("\n")
|
|
219
|
+
.map((line) => `// ${line}`) ?? [];
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Writes a block comment or inline postfix comment depending on the length of the content.
|
|
224
|
+
*/
|
|
225
|
+
function* writeDocumentationCommentFlexible(
|
|
226
|
+
decl: ProtoDeclaration,
|
|
227
|
+
output: string,
|
|
228
|
+
indentLevel: number
|
|
229
|
+
): Iterable<string> {
|
|
230
|
+
const docComment = decl.doc?.trim();
|
|
231
|
+
const docCommentIsOneLine = docComment && !docComment?.includes("\n");
|
|
232
|
+
|
|
233
|
+
const fullLength = indentLevel * 2 + output.length + 1 + (docComment?.length ?? 0);
|
|
234
|
+
|
|
235
|
+
if (docCommentIsOneLine && fullLength <= PROTO_MAX_ONE_LINE_DOC_LENGTH) {
|
|
236
|
+
yield output + " // " + decl.doc;
|
|
237
|
+
} else {
|
|
238
|
+
yield* writeBlockDocumentationComment(decl);
|
|
239
|
+
yield output;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
192
243
|
/**
|
|
193
244
|
* A version of flatMap that works with generic iterables.
|
|
194
245
|
*
|