@typespec/protobuf 0.43.0
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/.c8rc.json +3 -0
- package/.eslintrc.cjs +7 -0
- package/.mocharc.yaml +4 -0
- package/.rush/temp/operation/build/state.json +3 -0
- package/.rush/temp/operation/test-official/state.json +3 -0
- package/.rush/temp/package-deps_build.json +81 -0
- package/.rush/temp/package-deps_test-official.json +81 -0
- package/.rush/temp/shrinkwrap-deps.json +177 -0
- package/CHANGELOG.json +4 -0
- package/LICENSE +21 -0
- package/README.md +30 -0
- package/coverage/cobertura-coverage.xml +2291 -0
- package/coverage/coverage-final.json +7 -0
- package/coverage/tmp/coverage-6408-1683144315012-0.json +1 -0
- package/dist/src/ast.d.ts +199 -0
- package/dist/src/ast.d.ts.map +1 -0
- package/dist/src/ast.js +60 -0
- package/dist/src/ast.js.map +1 -0
- package/dist/src/index.d.ts +62 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +5 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lib.d.ts +197 -0
- package/dist/src/lib.d.ts.map +1 -0
- package/dist/src/lib.js +134 -0
- package/dist/src/lib.js.map +1 -0
- package/dist/src/proto.d.ts +62 -0
- package/dist/src/proto.d.ts.map +1 -0
- package/dist/src/proto.js +162 -0
- package/dist/src/proto.js.map +1 -0
- package/dist/src/transform/index.d.ts +7 -0
- package/dist/src/transform/index.d.ts.map +1 -0
- package/dist/src/transform/index.js +744 -0
- package/dist/src/transform/index.js.map +1 -0
- package/dist/src/write.d.ts +12 -0
- package/dist/src/write.d.ts.map +1 -0
- package/dist/src/write.js +204 -0
- package/dist/src/write.js.map +1 -0
- package/dist/test/scenarios.test.d.ts +2 -0
- package/dist/test/scenarios.test.d.ts.map +1 -0
- package/dist/test/scenarios.test.js +165 -0
- package/dist/test/scenarios.test.js.map +1 -0
- package/lib/proto.tsp +303 -0
- package/package.json +49 -0
- package/protobuf.build.log +48 -0
- package/src/ast.ts +279 -0
- package/src/index.ts +7 -0
- package/src/lib.ts +161 -0
- package/src/proto.ts +217 -0
- package/src/transform/index.ts +980 -0
- package/src/write.ts +244 -0
- package/temp/tsconfig.tsbuildinfo +1 -0
- package/test/include/foo/bar.proto +7 -0
- package/test/scenarios/addressbook/input/addressbook.tsp +27 -0
- package/test/scenarios/addressbook/input/main.tsp +13 -0
- package/test/scenarios/addressbook/output/@typespec/protobuf/addressbook.proto +26 -0
- package/test/scenarios/addressbook/output/@typespec/protobuf/main.proto +14 -0
- package/test/scenarios/anonymous-model/diagnostics.txt +1 -0
- package/test/scenarios/anonymous-model/input/main.tsp +24 -0
- package/test/scenarios/anonymous-package/input/main.tsp +19 -0
- package/test/scenarios/anonymous-package/output/@typespec/protobuf/main.proto +15 -0
- package/test/scenarios/array/input/main.tsp +22 -0
- package/test/scenarios/array/output/@typespec/protobuf/com/azure/test.proto +18 -0
- package/test/scenarios/array-nested/diagnostics.txt +1 -0
- package/test/scenarios/array-nested/input/main.tsp +20 -0
- package/test/scenarios/cross package references/input/main.tsp +27 -0
- package/test/scenarios/cross package references/output/@typespec/protobuf/A.proto +10 -0
- package/test/scenarios/cross package references/output/@typespec/protobuf/B.proto +15 -0
- package/test/scenarios/derived-scalar/input/main.tsp +24 -0
- package/test/scenarios/derived-scalar/output/@typespec/protobuf/com/azure/Test.proto +18 -0
- package/test/scenarios/enum/input/main.tsp +33 -0
- package/test/scenarios/enum/output/@typespec/protobuf/main.proto +31 -0
- package/test/scenarios/enum-nonintegral/diagnostics.txt +4 -0
- package/test/scenarios/enum-nonintegral/input/main.tsp +31 -0
- package/test/scenarios/enum-nozero/diagnostics.txt +1 -0
- package/test/scenarios/enum-nozero/input/main.tsp +25 -0
- package/test/scenarios/extern/input/main.tsp +17 -0
- package/test/scenarios/extern/output/@typespec/protobuf/main.proto +19 -0
- package/test/scenarios/illegal field reservations/diagnostics.txt +2 -0
- package/test/scenarios/illegal field reservations/input/main.tsp +16 -0
- package/test/scenarios/inferred-message-names/input/main.tsp +16 -0
- package/test/scenarios/inferred-message-names/output/@typespec/protobuf/com/azure/test.proto +18 -0
- package/test/scenarios/intrinsics/input/main.tsp +17 -0
- package/test/scenarios/intrinsics/output/@typespec/protobuf/com/azure/Test.proto +16 -0
- package/test/scenarios/map/input/main.tsp +15 -0
- package/test/scenarios/map/output/@typespec/protobuf/main.proto +13 -0
- package/test/scenarios/model-no-package/diagnostics.txt +2 -0
- package/test/scenarios/model-no-package/input/main.tsp +19 -0
- package/test/scenarios/name-collision/input/main.tsp +24 -0
- package/test/scenarios/name-collision/output/@typespec/protobuf/main.proto +24 -0
- package/test/scenarios/options/input/main.tsp +25 -0
- package/test/scenarios/options/output/@typespec/protobuf/com/azure/Test.proto +20 -0
- package/test/scenarios/options-invalid/diagnostics.txt +1 -0
- package/test/scenarios/options-invalid/input/main.tsp +25 -0
- package/test/scenarios/reserved field collisions/diagnostics.txt +5 -0
- package/test/scenarios/reserved field collisions/input/main.tsp +19 -0
- package/test/scenarios/reserved fields/input/main.tsp +16 -0
- package/test/scenarios/reserved fields/output/@typespec/protobuf/main.proto +16 -0
- package/test/scenarios/simple/input/main.tsp +22 -0
- package/test/scenarios/simple/output/@typespec/protobuf/com/azure/Test.proto +18 -0
- package/test/scenarios/simple-error/diagnostics.txt +6 -0
- package/test/scenarios/simple-error/input/main.tsp +22 -0
- package/test/scenarios/simple-no-service/input/main.tsp +22 -0
- package/test/scenarios/simple-no-service/output/@typespec/protobuf/com/azure/Test.proto +18 -0
- package/test/scenarios/streams/input/main.tsp +30 -0
- package/test/scenarios/streams/output/@typespec/protobuf/main.proto +19 -0
- package/test/scenarios/type-validation/diagnostics.txt +1 -0
- package/test/scenarios/type-validation/input/main.tsp +11 -0
- package/test/scenarios/union/diagnostics.txt +1 -0
- package/test/scenarios/union/input/main.tsp +33 -0
- package/test/scenarios.test.ts +226 -0
- package/tsconfig.json +15 -0
package/src/lib.ts
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT license.
|
|
3
|
+
|
|
4
|
+
import { createTypeSpecLibrary, JSONSchemaType, paramMessage } from "@typespec/compiler";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Options that the Protobuf emitter accepts.
|
|
8
|
+
*/
|
|
9
|
+
export interface ProtobufEmitterOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Don't emit anything.
|
|
12
|
+
*/
|
|
13
|
+
noEmit?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const EmitterOptionsSchema: JSONSchemaType<ProtobufEmitterOptions> = {
|
|
17
|
+
type: "object",
|
|
18
|
+
additionalProperties: false,
|
|
19
|
+
properties: {
|
|
20
|
+
noEmit: { type: "boolean", nullable: true },
|
|
21
|
+
},
|
|
22
|
+
required: [],
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const PACKAGE_NAME = "@typespec/protobuf";
|
|
26
|
+
|
|
27
|
+
export const TypeSpecProtobufLibrary = createTypeSpecLibrary({
|
|
28
|
+
name: PACKAGE_NAME,
|
|
29
|
+
requireImports: [PACKAGE_NAME],
|
|
30
|
+
diagnostics: {
|
|
31
|
+
"field-index": {
|
|
32
|
+
severity: "error",
|
|
33
|
+
messages: {
|
|
34
|
+
missing: paramMessage`field ${"name"} does not have a field index, but one is required (try using the '@field' decorator)`,
|
|
35
|
+
invalid: paramMessage`field index ${"index"} is invalid (must be an integer greater than zero)`,
|
|
36
|
+
"out-of-bounds": paramMessage`field index ${"index"} is out of bounds (must be less than ${"max"})`,
|
|
37
|
+
reserved: paramMessage`field index ${"index"} falls within the implementation-reserved range of 19000-19999 inclusive`,
|
|
38
|
+
"user-reserved": paramMessage`field index ${"index"} was reserved by a call to @reserve on this model`,
|
|
39
|
+
"user-reserved-range": paramMessage`field index ${"index"} falls within a range reserved by a call to @reserve on this model`,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
"field-name": {
|
|
43
|
+
severity: "error",
|
|
44
|
+
messages: {
|
|
45
|
+
"user-reserved": paramMessage`field name '${"name"}' was reserved by a call to @reserve on this model`,
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
"root-operation": {
|
|
49
|
+
severity: "error",
|
|
50
|
+
messages: {
|
|
51
|
+
default:
|
|
52
|
+
"operations in the root namespace are not supported (no associated Protobuf service)",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
"unsupported-intrinsic": {
|
|
56
|
+
severity: "error",
|
|
57
|
+
messages: {
|
|
58
|
+
default: paramMessage`intrinsic type ${"name"} is not supported in Protobuf`,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
"unsupported-return-type": {
|
|
62
|
+
severity: "error",
|
|
63
|
+
messages: {
|
|
64
|
+
default: "Protobuf methods must return a named Model",
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
"unsupported-input-type": {
|
|
68
|
+
severity: "error",
|
|
69
|
+
messages: {
|
|
70
|
+
"wrong-number":
|
|
71
|
+
"Protobuf methods must accept exactly one Model input (an empty model will do)",
|
|
72
|
+
"wrong-type": "Protobuf methods may only accept a named Model as an input",
|
|
73
|
+
unconvertible: "input parameters cannot be converted to a Protobuf message",
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
"unsupported-field-type": {
|
|
77
|
+
severity: "error",
|
|
78
|
+
messages: {
|
|
79
|
+
unconvertible: paramMessage`cannot convert a ${"type"} to a protobuf type (only intrinsic types and models are supported)`,
|
|
80
|
+
"unknown-intrinsic": paramMessage`no known protobuf scalar for intrinsic type ${"name"}`,
|
|
81
|
+
"unknown-scalar": paramMessage`no known protobuf scalar for TypeSpec scalar type ${"name"}`,
|
|
82
|
+
"recursive-map": "a protobuf map's 'value' type may not refer to another map",
|
|
83
|
+
union: "a message field's type may not be a union",
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
"namespace-collision": {
|
|
87
|
+
severity: "error",
|
|
88
|
+
messages: {
|
|
89
|
+
default: paramMessage`the package name ${"name"} has already been used`,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
"unconvertible-enum": {
|
|
93
|
+
severity: "error",
|
|
94
|
+
messages: {
|
|
95
|
+
default:
|
|
96
|
+
"enums must explicitly assign exactly one integer to each member to be used in a Protobuf message",
|
|
97
|
+
"no-zero-first":
|
|
98
|
+
"the first variant of an enum must be set to zero to be used in a Protobuf message",
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
"nested-array": {
|
|
102
|
+
severity: "error",
|
|
103
|
+
messages: {
|
|
104
|
+
default: "nested arrays are not supported by the Protobuf emitter",
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
"invalid-package-name": {
|
|
108
|
+
severity: "error",
|
|
109
|
+
messages: {
|
|
110
|
+
default: paramMessage`${"name"} is not a valid package name (must consist of letters and numbers separated by ".")`,
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
"illegal-reservation": {
|
|
114
|
+
severity: "error",
|
|
115
|
+
messages: {
|
|
116
|
+
default:
|
|
117
|
+
"reservation value must be a string literal, uint32 literal, or a tuple of two uint32 literals denoting a range",
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
"model-not-in-package": {
|
|
121
|
+
severity: "error",
|
|
122
|
+
messages: {
|
|
123
|
+
default: paramMessage`model ${"name"} is not in a namespace that uses the '@Protobuf.package' decorator`,
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
"anonymous-model": {
|
|
127
|
+
severity: "error",
|
|
128
|
+
messages: {
|
|
129
|
+
default: "anonymous models cannot be used in Protobuf messages",
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
package: {
|
|
133
|
+
severity: "error",
|
|
134
|
+
messages: {
|
|
135
|
+
"disallowed-option-type": paramMessage`option '${"name"}' with type '${"type"}' is not allowed in a package declaration (only string, boolean, and numeric types are allowed)`,
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
emitter: { options: EmitterOptionsSchema },
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
export const { reportDiagnostic } = TypeSpecProtobufLibrary;
|
|
143
|
+
|
|
144
|
+
export type TypeSpecProtobufLibrary = typeof TypeSpecProtobufLibrary;
|
|
145
|
+
|
|
146
|
+
const keys = [
|
|
147
|
+
"fieldIndex",
|
|
148
|
+
"package",
|
|
149
|
+
"service",
|
|
150
|
+
"externRef",
|
|
151
|
+
"stream",
|
|
152
|
+
"reserve",
|
|
153
|
+
"message",
|
|
154
|
+
"_map",
|
|
155
|
+
] as const;
|
|
156
|
+
|
|
157
|
+
export const state = Object.fromEntries(
|
|
158
|
+
keys.map((k) => [k, TypeSpecProtobufLibrary.createStateSymbol(k)])
|
|
159
|
+
) as {
|
|
160
|
+
[K in (typeof keys)[number]]: symbol;
|
|
161
|
+
};
|
package/src/proto.ts
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT license.
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
DecoratorContext,
|
|
6
|
+
EmitContext,
|
|
7
|
+
EmitOptionsFor,
|
|
8
|
+
EnumMember,
|
|
9
|
+
Interface,
|
|
10
|
+
Model,
|
|
11
|
+
ModelProperty,
|
|
12
|
+
Namespace,
|
|
13
|
+
NumericLiteral,
|
|
14
|
+
Operation,
|
|
15
|
+
Program,
|
|
16
|
+
resolvePath,
|
|
17
|
+
Tuple,
|
|
18
|
+
Type,
|
|
19
|
+
} from "@typespec/compiler";
|
|
20
|
+
|
|
21
|
+
import { StreamingMode } from "./ast.js";
|
|
22
|
+
import { ProtobufEmitterOptions, reportDiagnostic, state, TypeSpecProtobufLibrary } from "./lib.js";
|
|
23
|
+
import { createProtobufEmitter } from "./transform/index.js";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* # @typespec/protobuf : Protobuf/gRPC Emitter and Decorators for TypeSpec
|
|
27
|
+
*
|
|
28
|
+
* This module defines an emitter and decorator library for TypeSpec that enables specifying Protobuf services and models.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The maximum field index allowed by Protocol Buffers.
|
|
33
|
+
*/
|
|
34
|
+
const MAX_FIELD_INDEX = 2 ** 29 - 1;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The field range between 19000 and 19999 is reserved for Protobuf client implementations.
|
|
38
|
+
*/
|
|
39
|
+
const IMPLEMENTATION_RESERVED_RANGE = [19000, 19999] as const;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Defined in the [ProtoBuf Language Spec](https://developers.google.com/protocol-buffers/docs/reference/proto3-spec#identifiers).
|
|
43
|
+
*
|
|
44
|
+
* ident = letter \{ letter | decimalDigit | "_" \}
|
|
45
|
+
* fullIdent = ident \{ "." ident \}
|
|
46
|
+
*/
|
|
47
|
+
export const PROTO_FULL_IDENT = /([a-zA-Z][a-zA-Z0-9_]*)+/;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Decorate an interface as a service, indicating that it represents a Protobuf `service` declaration.
|
|
51
|
+
*
|
|
52
|
+
* @param ctx - decorator context
|
|
53
|
+
* @param target - the decorated interface
|
|
54
|
+
*/
|
|
55
|
+
export function $service(ctx: DecoratorContext, target: Interface) {
|
|
56
|
+
ctx.program.stateSet(state.service).add(target);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface PackageDetails {
|
|
60
|
+
name?: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Declare a Protobuf package.
|
|
65
|
+
*
|
|
66
|
+
* @param ctx - decorator context
|
|
67
|
+
* @param target - target decorator namespace
|
|
68
|
+
*/
|
|
69
|
+
export function $package(ctx: DecoratorContext, target: Namespace, details?: Model) {
|
|
70
|
+
ctx.program.stateMap(state.package).set(target, details);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Determines whether a type represents a Protobuf map.
|
|
75
|
+
*
|
|
76
|
+
* @param program - the program context
|
|
77
|
+
* @param m - the type to test
|
|
78
|
+
* @returns true if the internal representation of a Protobuf map is bound to this type.
|
|
79
|
+
*/
|
|
80
|
+
export function isMap(program: Program, m: Type): boolean {
|
|
81
|
+
return program.stateSet(state._map).has(m);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Binds the internal representation of a Protobuf map.
|
|
86
|
+
* @internal
|
|
87
|
+
* @param ctx
|
|
88
|
+
* @param target
|
|
89
|
+
*/
|
|
90
|
+
export function $_map(ctx: DecoratorContext, target: Model) {
|
|
91
|
+
ctx.program.stateSet(state._map).add(target);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function $externRef(ctx: DecoratorContext, target: Model, path: string, name: string) {
|
|
95
|
+
ctx.program.stateMap(state.externRef).set(target, [path, name]);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function $stream(ctx: DecoratorContext, target: Operation, mode: EnumMember) {
|
|
99
|
+
const emitStreamingMode = {
|
|
100
|
+
Duplex: StreamingMode.Duplex,
|
|
101
|
+
In: StreamingMode.In,
|
|
102
|
+
Out: StreamingMode.Out,
|
|
103
|
+
None: StreamingMode.None,
|
|
104
|
+
}[mode.name as string];
|
|
105
|
+
|
|
106
|
+
ctx.program.stateMap(state.stream).set(target, emitStreamingMode);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function getTuple(program: Program, t: Type): [number, number] | null {
|
|
110
|
+
if (t.kind !== "Tuple" || t.values.some((v) => v.kind !== "Number") || t.values.length !== 2) {
|
|
111
|
+
reportDiagnostic(program, {
|
|
112
|
+
code: "illegal-reservation",
|
|
113
|
+
target: t,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return Object.assign(
|
|
120
|
+
(t as Tuple).values.map((v) => (v as NumericLiteral).value) as [number, number],
|
|
121
|
+
{ type: t }
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export type Reservation = string | number | ([number, number] & { type: Type });
|
|
126
|
+
|
|
127
|
+
export function $reserve(
|
|
128
|
+
ctx: DecoratorContext,
|
|
129
|
+
target: Model,
|
|
130
|
+
...reservations: readonly (Type | number | string)[]
|
|
131
|
+
) {
|
|
132
|
+
const finalReservations = reservations
|
|
133
|
+
.map((reservation) =>
|
|
134
|
+
typeof reservation === "object" ? getTuple(ctx.program, reservation) : reservation
|
|
135
|
+
)
|
|
136
|
+
.filter((v) => v != null);
|
|
137
|
+
|
|
138
|
+
ctx.program.stateMap(state.reserve).set(target, finalReservations);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function $message(ctx: DecoratorContext, target: Model) {
|
|
142
|
+
ctx.program.stateSet(state.message).add(target);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Decorate a model property with a field index. Field indices are required for all fields of emitted messages.
|
|
147
|
+
*
|
|
148
|
+
* @param param0
|
|
149
|
+
* @param target
|
|
150
|
+
* @param fieldIndex
|
|
151
|
+
* @returns
|
|
152
|
+
*/
|
|
153
|
+
export function $field(ctx: DecoratorContext, target: ModelProperty, fieldIndex: number) {
|
|
154
|
+
if (!Number.isInteger(fieldIndex) || fieldIndex <= 0) {
|
|
155
|
+
reportDiagnostic(ctx.program, {
|
|
156
|
+
code: "field-index",
|
|
157
|
+
messageId: "invalid",
|
|
158
|
+
format: {
|
|
159
|
+
index: String(fieldIndex),
|
|
160
|
+
},
|
|
161
|
+
target,
|
|
162
|
+
});
|
|
163
|
+
return;
|
|
164
|
+
} else if (fieldIndex > MAX_FIELD_INDEX) {
|
|
165
|
+
reportDiagnostic(ctx.program, {
|
|
166
|
+
code: "field-index",
|
|
167
|
+
messageId: "out-of-bounds",
|
|
168
|
+
format: {
|
|
169
|
+
index: String(fieldIndex),
|
|
170
|
+
max: String(MAX_FIELD_INDEX + 1),
|
|
171
|
+
},
|
|
172
|
+
target,
|
|
173
|
+
});
|
|
174
|
+
return;
|
|
175
|
+
} else if (
|
|
176
|
+
fieldIndex >= IMPLEMENTATION_RESERVED_RANGE[0] &&
|
|
177
|
+
fieldIndex <= IMPLEMENTATION_RESERVED_RANGE[1]
|
|
178
|
+
) {
|
|
179
|
+
reportDiagnostic(ctx.program, {
|
|
180
|
+
code: "field-index",
|
|
181
|
+
messageId: "reserved",
|
|
182
|
+
format: {
|
|
183
|
+
index: String(fieldIndex),
|
|
184
|
+
},
|
|
185
|
+
target,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
ctx.program.stateMap(state.fieldIndex).set(target, fieldIndex);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Emitter main function.
|
|
194
|
+
*
|
|
195
|
+
* @param program - the program to emit
|
|
196
|
+
*/
|
|
197
|
+
export async function $onEmit(ctx: EmitContext<EmitOptionsFor<TypeSpecProtobufLibrary>>) {
|
|
198
|
+
const emitter = createProtobufEmitter(ctx.program);
|
|
199
|
+
|
|
200
|
+
await emitter(resolvePath(ctx.emitterOutputDir), ctx.options);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Validation function
|
|
205
|
+
*/
|
|
206
|
+
export async function $onValidate(program: Program) {
|
|
207
|
+
// Is this correct? See https://github.com/microsoft/typespec/issues/1859
|
|
208
|
+
/* c8 ignore next 6 */
|
|
209
|
+
if (program.compilerOptions.noEmit) {
|
|
210
|
+
const options = program.emitters.find((e) => e.emitFunction === $onEmit)
|
|
211
|
+
?.options as ProtobufEmitterOptions;
|
|
212
|
+
const emitter = createProtobufEmitter(program);
|
|
213
|
+
await emitter("", options);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export const namespace = "TypeSpec.Protobuf";
|