diff --git a/packages/http-client-csharp/.tspd/docs/usage.md b/packages/http-client-csharp/.tspd/docs/usage.md index 7db6449e111..df102df83f2 100644 --- a/packages/http-client-csharp/.tspd/docs/usage.md +++ b/packages/http-client-csharp/.tspd/docs/usage.md @@ -6,3 +6,80 @@ ### Customizing Generated Code For detailed instructions on how to customize the generated C# code, see the [Customization Guide](https://github.com/microsoft/typespec/blob/main/packages/http-client-csharp/.tspd/docs/customization.md). + +### Experimental types and members + +Use `@TypeSpec.HttpClient.experimental` to assign a public diagnostic ID to a generated +type or member and identify experiments used by its implementation: + +```typespec +import "@typespec/http-client"; + +@TypeSpec.HttpClient.experimental(#{ + emitterScope: "@typespec/http-client-csharp", + diagnosticId: "C", + dependsOn: #["A", "B"], +}) +op bar(): void; +``` + +The C# emitter adds `[Experimental("C")]` to the corresponding generated declaration: + +| TypeSpec target | Generated C# target | +| ----------------------------------------------------- | ------------------------------------------------------------- | +| Model | Model class or struct | +| Model property | Property | +| Enum or union emitted as an enum | Enum or extensible-enum struct | +| Enum member or union variant emitted as an enum value | Enum field or extensible-enum property | +| Operation | Synchronous and asynchronous protocol and convenience methods | +| Namespace or interface emitted as a client | Client class | + +For example, models and their properties can be separate experiments: + +```typespec +@TypeSpec.HttpClient.experimental(#{ diagnosticId: "MODEL001" }) +model Preview { + @TypeSpec.HttpClient.experimental(#{ diagnosticId: "PROPERTY001" }) + value?: string; +} +``` + +Model factory methods expose the model's diagnostic. Partial serialization declarations +do not repeat the model attribute. Generated code suppresses diagnostics when referring +to source-annotated experimental types and members, so serialization, factories, and client +implementations can compile without changing the experimental status of other public APIs. + +For operation dependencies, suppressions surround each method declaration and body. +For type/member dependencies and generated references to experimental declarations, +suppressions are scoped to the generated file. Both include parameter and return types, +generic arguments, and implementation references; neither suppresses diagnostics in +consumer code. + +Dependencies identify diagnostics rather than individual types: one diagnostic can apply +to multiple types or members, including those defined in external libraries. For externally +mapped types, source `@experimental` metadata is retained for generated-reference suppressions; +the emitter does not generate the external declaration or add attributes to its library. +Other external experiments require explicit `dependsOn` entries. They are not discovered by reflection. + +Both metadata fields are optional. Without `diagnosticId`, no public experimental attribute +is added. Without `dependsOn`, no additional dependency diagnostics are requested; generated +references to source-annotated experiments are still handled. Emitter scopes apply to both fields. + +Diagnostic IDs must be single C# warning identifiers (ASCII letters, digits, and underscores, +not starting with a digit) or decimal warning numbers. Whitespace, punctuation, comments, and +line breaks are rejected with `invalid-experimental-diagnostic-id` before generating C#. +An `ExperimentalAttribute` on a customized partial client or method takes precedence over +the generated attribute. + +Some TypeSpec declarations have no corresponding C# declaration, such as scalars or unions +erased to built-in C# types without an explicit external mapping. C# also does not allow `ExperimentalAttribute` on parameters. +The emitter reports `experimental-target-not-supported` for these annotations instead of +silently dropping them or assigning their diagnostic to an unrelated API. + +Models referenced by a union retain their own experimental metadata. Annotate the model +declaration, not the union variant that references it: a model variant has no separate C# +declaration on which to place an attribute. + +Graduation is an explicit source change: dependencies becoming generally available, or +removing entries from `dependsOn`, does not remove `[Experimental("C")]`. Remove the +declaration's `@experimental` decorator when the public API is ready to graduate. diff --git a/packages/http-client-csharp/emitter/src/lib/client-converter.ts b/packages/http-client-csharp/emitter/src/lib/client-converter.ts index 69a49c614d6..40a1f98b502 100644 --- a/packages/http-client-csharp/emitter/src/lib/client-converter.ts +++ b/packages/http-client-csharp/emitter/src/lib/client-converter.ts @@ -19,6 +19,7 @@ import type { InputParameter, InputType, } from "../type/input-type.js"; +import { getExperimentalDetails } from "./experimental.js"; import { createDiagnostic } from "./lib.js"; import { fromMethodParameter, @@ -101,6 +102,7 @@ function fromSdkClient( parent: undefined, children: undefined, isMultiServiceClient: isMultiService, + experimental: diagnostics.pipe(getExperimentalDetails(sdkContext, client.__raw.type)), }; sdkContext.__typeCache.updateSdkClientReferences(client, inputClient); diff --git a/packages/http-client-csharp/emitter/src/lib/experimental.ts b/packages/http-client-csharp/emitter/src/lib/experimental.ts new file mode 100644 index 00000000000..d7bc23db00e --- /dev/null +++ b/packages/http-client-csharp/emitter/src/lib/experimental.ts @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import type { SdkContext } from "@azure-tools/typespec-client-generator-core"; +import type { Diagnostic, Type } from "@typespec/compiler"; +import { createDiagnosticCollector } from "@typespec/compiler"; +import { $ } from "@typespec/compiler/typekit"; +import "@typespec/http-client/typekit"; +import type { InputExperimentalDetails } from "../type/input-type.js"; +import { createDiagnostic } from "./lib.js"; + +export function getExperimentalDetails( + context: SdkContext, + target: Type | undefined, + supportsExperimentalMetadata = true, +): [InputExperimentalDetails | undefined, readonly Diagnostic[]] { + const diagnostics = createDiagnosticCollector(); + if (!target) { + return diagnostics.wrap(undefined); + } + + const lifecycle = diagnostics.pipe( + $(context.program).client.getFeatureLifecycleDetails.withDiagnostics(target, { + emitterName: "@typespec/http-client-csharp", + }), + ); + if (lifecycle && !supportsExperimentalMetadata) { + diagnostics.add(createDiagnostic({ code: "experimental-target-not-supported", target })); + return diagnostics.wrap(undefined); + } + + if (lifecycle) { + const ids = [ + ...(lifecycle.diagnosticId === undefined ? [] : [lifecycle.diagnosticId]), + ...lifecycle.dependsOn, + ]; + for (const id of new Set(ids)) { + if (id.match(/^(?:[A-Za-z_][A-Za-z0-9_]*|[0-9]+)/u)?.[0] !== id) { + diagnostics.add( + createDiagnostic({ + code: "invalid-experimental-diagnostic-id", + target, + format: { diagnosticId: JSON.stringify(id) }, + }), + ); + } + } + if (diagnostics.diagnostics.length > 0) { + return diagnostics.wrap(undefined); + } + } + + return diagnostics.wrap( + lifecycle + ? { diagnosticId: lifecycle.diagnosticId, dependsOn: [...lifecycle.dependsOn] } + : undefined, + ); +} diff --git a/packages/http-client-csharp/emitter/src/lib/lib.ts b/packages/http-client-csharp/emitter/src/lib/lib.ts index b82bab80f0b..1f6a052ce64 100644 --- a/packages/http-client-csharp/emitter/src/lib/lib.ts +++ b/packages/http-client-csharp/emitter/src/lib/lib.ts @@ -10,6 +10,19 @@ export type DiagnosticMessagesMap = { }; const diags: { [code: string]: DiagnosticDefinition } = { + "invalid-experimental-diagnostic-id": { + severity: "error", + messages: { + default: paramMessage`Experimental diagnostic ID ${"diagnosticId"} must be a single C# warning identifier (ASCII letters, digits, or underscores, not starting with a digit) or a decimal warning number.`, + }, + }, + "experimental-target-not-supported": { + severity: "error", + messages: { + default: + "This experimental declaration does not produce a C# type or member that supports ExperimentalAttribute. Apply @experimental to an emitted model, enum, property, enum member, operation, or client instead.", + }, + }, "no-apiVersion": { severity: "error", messages: { diff --git a/packages/http-client-csharp/emitter/src/lib/operation-converter.ts b/packages/http-client-csharp/emitter/src/lib/operation-converter.ts index 10696a9a315..f7f4f0ccd75 100644 --- a/packages/http-client-csharp/emitter/src/lib/operation-converter.ts +++ b/packages/http-client-csharp/emitter/src/lib/operation-converter.ts @@ -78,6 +78,7 @@ import { parseHttpRequestMethod } from "../type/request-method.js"; import { ResponseLocation } from "../type/response-location.js"; import { getExternalDocs, getOperationId } from "./decorators.js"; import { fromSdkHttpExamples } from "./example-converter.js"; +import { getExperimentalDetails } from "./experimental.js"; import { createDiagnostic } from "./lib.js"; import { fromSdkType } from "./type-converter.js"; import { getClientNamespaceString, isReadOnly } from "./utils.js"; @@ -252,6 +253,9 @@ export function fromSdkServiceMethodOperation( namespace: method.__raw?.namespace ? getClientNamespace(sdkContext, method.__raw.namespace) : undefined, + experimental: diagnostics.pipe( + getExperimentalDetails(sdkContext, method.operation.__raw.operation), + ), }; sdkContext.__typeCache.updateSdkOperationReferences(method.operation, operation); @@ -686,6 +690,8 @@ export function fromMethodParameter( return diagnostics.wrap(retVar as InputMethodParameter); } + // C# cannot apply ExperimentalAttribute directly to a parameter. + diagnostics.pipe(getExperimentalDetails(sdkContext, p.__raw, false)); const parameterType = diagnostics.pipe(fromSdkType(sdkContext, p.type, p, namespace)); const paramAlias = p.__raw ? getParamAlias(sdkContext, p.__raw) : undefined; diff --git a/packages/http-client-csharp/emitter/src/lib/type-converter.ts b/packages/http-client-csharp/emitter/src/lib/type-converter.ts index 0d98baeb7a8..a0fcaf7ff10 100644 --- a/packages/http-client-csharp/emitter/src/lib/type-converter.ts +++ b/packages/http-client-csharp/emitter/src/lib/type-converter.ts @@ -43,6 +43,7 @@ import type { InputType, InputUnionType, } from "../type/input-type.js"; +import { getExperimentalDetails } from "./experimental.js"; import { createDiagnostic } from "./lib.js"; import { isReadOnly } from "./utils.js"; @@ -189,6 +190,22 @@ export function fromSdkType( break; } + // External declarations are not emitted, but their known diagnostics apply at generated reference sites. + retVar.experimental = diagnostics.pipe( + getExperimentalDetails( + sdkContext, + sdkType.__raw, + retVar.external !== undefined || + (retVar.kind === "model" && !retVar.isFileType) || + retVar.kind === "enum" || + retVar.kind === "enumvalue", + ), + ); + if (sdkType.__raw?.kind === "Union" && retVar.kind !== "enum") { + for (const variant of sdkType.__raw.variants.values()) { + diagnostics.pipe(getExperimentalDetails(sdkContext, variant, false)); + } + } sdkContext.__typeCache.updateSdkTypeReferences(sdkType, retVar); // we have to cast to any because TypeScript's type narrowing does not automatically infer the return type for conditional types return diagnostics.wrap(retVar as any); @@ -300,6 +317,7 @@ function fromSdkModelProperty( isHttpMetadata: isHttpMetadata(sdkContext, sdkProperty), encode: sdkProperty.encode, isExactName: sdkProperty.isExactName, + experimental: diagnostics.pipe(getExperimentalDetails(sdkContext, sdkProperty.__raw)), } as InputModelProperty; if (sdkProperty.serializationOptions?.multipart?.isFilePart === true) { @@ -520,6 +538,7 @@ function createEnumValueType( doc: sdkType.doc, decorators: sdkType.decorators, isExactName: sdkType.isExactName, + experimental: diagnostics.pipe(getExperimentalDetails(sdkContext, sdkType.__raw)), }); } diff --git a/packages/http-client-csharp/emitter/src/type/input-operation.ts b/packages/http-client-csharp/emitter/src/type/input-operation.ts index 809719303e7..fba46b91ed2 100644 --- a/packages/http-client-csharp/emitter/src/type/input-operation.ts +++ b/packages/http-client-csharp/emitter/src/type/input-operation.ts @@ -3,7 +3,7 @@ import type { DecoratorInfo } from "@azure-tools/typespec-client-generator-core"; import type { InputHttpOperationExample } from "./input-examples.js"; -import type { InputHttpParameter } from "./input-type.js"; +import type { InputExperimentalDetails, InputHttpParameter } from "./input-type.js"; import type { OperationResponse } from "./operation-response.js"; import type { RequestMethod } from "./request-method.js"; @@ -29,4 +29,5 @@ export interface InputOperation { crossLanguageDefinitionId: string; decorators?: DecoratorInfo[]; namespace?: string; + experimental?: InputExperimentalDetails; } diff --git a/packages/http-client-csharp/emitter/src/type/input-type.ts b/packages/http-client-csharp/emitter/src/type/input-type.ts index 73e2ade590a..691e831176a 100644 --- a/packages/http-client-csharp/emitter/src/type/input-type.ts +++ b/packages/http-client-csharp/emitter/src/type/input-type.ts @@ -59,6 +59,12 @@ export interface InputNamespace extends DecoratedType { interface DecoratedType { decorators?: DecoratorInfo[]; + experimental?: InputExperimentalDetails; +} + +export interface InputExperimentalDetails { + diagnosticId?: string; + dependsOn: string[]; } interface InputTypeBase extends DecoratedType { diff --git a/packages/http-client-csharp/emitter/test/Unit/decorator-list.test.ts b/packages/http-client-csharp/emitter/test/Unit/decorator-list.test.ts index 05039192bd4..112070d2712 100644 --- a/packages/http-client-csharp/emitter/test/Unit/decorator-list.test.ts +++ b/packages/http-client-csharp/emitter/test/Unit/decorator-list.test.ts @@ -5,6 +5,7 @@ import { expectDiagnostics, type TestHost, } from "@typespec/compiler/testing"; +import { HttpClientTestLibrary } from "@typespec/http-client/testing"; import { deepStrictEqual, strictEqual } from "assert"; import { ok } from "assert/strict"; import { beforeEach, describe, it, vi } from "vitest"; @@ -23,6 +24,318 @@ describe("Test emitting decorator list", () => { runner = await createEmitterTestHost(); }); + describe("experimental declarations", () => { + beforeEach(async () => { + await runner.addTypeSpecLibrary(HttpClientTestLibrary); + }); + + it.each([ + `@TypeSpec.HttpClient.experimental(#{ diagnosticId: "TYPE001" }) + model Payload { value: string; } op read(@body value: Payload): void;`, + `@TypeSpec.HttpClient.experimental(#{ diagnosticId: "TYPE001" }) + enum Choice { One, Two } op read(@query value: Choice): void;`, + ])("keeps parameter-type metadata without annotating the parameter", async (code) => { + const program = await typeSpecCompile(code, runner, { IsHttpClientNeeded: true }); + const sdkContext = await createCSharpSdkContext(createEmitterContext(program)); + const [root, diagnostics] = createModel(sdkContext); + expectDiagnosticEmpty(diagnostics); + const parameter = root.clients[0].methods[0].parameters.find((p) => p.name === "value")!; + strictEqual(parameter.experimental, undefined); + deepStrictEqual(parameter.type.experimental, { diagnosticId: "TYPE001", dependsOn: [] }); + }); + + describe.each(["diagnosticId", "dependsOn"])("validating %s", (field) => { + it.each([ + "", + " ", + "A B", + "A,B", + "A-B", + "A.B", + "1A", + "@A", + "A\n", + "A\r", + "A\tB", + "A//B", + "A/*B*/", + "A\n#pragma warning disable", + ])("rejects invalid ID %j", async (id) => { + const value = field === "dependsOn" ? `#[${JSON.stringify(id)}]` : JSON.stringify(id); + const program = await typeSpecCompile( + `@TypeSpec.HttpClient.experimental(#{ ${field}: ${value} }) op read(): void;`, + runner, + { IsHttpClientNeeded: true }, + ); + const sdkContext = await createCSharpSdkContext(createEmitterContext(program)); + const [, diagnostics] = createModel(sdkContext); + expectDiagnostics(diagnostics, { + code: "@typespec/http-client-csharp/invalid-experimental-diagnostic-id", + }); + }); + }); + + it.each(["A", "DEP001", "_DEP001", "CS0618", "0618", "class"])( + "accepts pragma identifier %s", + async (id) => { + const program = await typeSpecCompile( + `@TypeSpec.HttpClient.experimental(#{ diagnosticId: "${id}", dependsOn: #["${id}"] }) op read(): void;`, + runner, + { IsHttpClientNeeded: true }, + ); + const sdkContext = await createCSharpSdkContext(createEmitterContext(program)); + const [root, diagnostics] = createModel(sdkContext); + expectDiagnosticEmpty(diagnostics); + deepStrictEqual(root.clients[0].methods[0].operation.experimental, { + diagnosticId: id, + dependsOn: [id], + }); + }, + ); + + const declarations = [ + { + name: "model", + code: `DECORATOR model Payload { value: string; } op read(): Payload;`, + select: (root: ReturnType[0]) => root.models[0], + }, + { + name: "model property", + code: `model Payload { DECORATOR value: string; } op read(): Payload;`, + select: (root: ReturnType[0]) => root.models[0].properties[0], + }, + { + name: "enum", + code: `DECORATOR enum Choice { One, Two } op read(): Choice;`, + select: (root: ReturnType[0]) => root.enums[0], + }, + { + name: "enum member", + code: `enum Choice { DECORATOR One, Two } op read(): Choice;`, + select: (root: ReturnType[0]) => root.enums[0].values[0], + }, + { + name: "extensible enum", + code: `DECORATOR union Choice { string, One: "one", Two: "two" } op read(): Choice;`, + select: (root: ReturnType[0]) => root.enums[0], + }, + { + name: "union variant", + code: `union Choice { string, DECORATOR One: "one", Two: "two" } op read(): Choice;`, + select: (root: ReturnType[0]) => root.enums[0].values[0], + }, + { + name: "interface client", + code: `DECORATOR interface Group { @route("/read") read(): void; }`, + select: (root: ReturnType[0]) => root.clients[0].children![0], + }, + { + name: "namespace client", + code: `DECORATOR namespace Group { @route("/read") op read(): void; }`, + select: (root: ReturnType[0]) => root.clients[0].children![0], + }, + ]; + + describe.each(declarations)("$name", ({ code, select }) => { + it.each([ + { scope: "@typespec/http-client-csharp", applies: true }, + { scope: "other-emitter", applies: false }, + { scope: "!other-emitter", applies: true }, + ])("preserves scoped metadata for $scope", async ({ scope, applies }) => { + const decorator = `@TypeSpec.HttpClient.experimental(#{ + emitterScope: "${scope}", diagnosticId: "TEST001", dependsOn: #["DEP001", "DEP002"] + })`; + const program = await typeSpecCompile(code.replace("DECORATOR", decorator), runner, { + IsHttpClientNeeded: true, + }); + const sdkContext = await createCSharpSdkContext(createEmitterContext(program)); + expectDiagnosticEmpty(sdkContext.diagnostics); + const [root, diagnostics] = createModel(sdkContext); + expectDiagnosticEmpty(diagnostics); + deepStrictEqual( + select(root).experimental, + applies ? { diagnosticId: "TEST001", dependsOn: ["DEP001", "DEP002"] } : undefined, + ); + }); + }); + + describe.each([ + { + name: "named model variants", + declaration: "union Choice { preview: Preview, stable: Stable }", + type: "Choice", + }, + { + name: "unnamed model variants", + declaration: "union Choice { Preview, Stable }", + type: "Choice", + }, + { + name: "inline model variants", + declaration: "", + type: "Preview | Stable", + }, + { + name: "nullable model variants", + declaration: "union Choice { preview: Preview, stable: Stable, null }", + type: "Choice", + }, + { + name: "a nullable model", + declaration: "union Choice { preview: Preview, null }", + type: "Choice", + }, + { + name: "mixed model and scalar variants", + declaration: "union Choice { preview: Preview, text: string }", + type: "Choice", + }, + ])("experimental models in $name", ({ declaration, type }) => { + it.each([ + { scope: "@typespec/http-client-csharp", applies: true }, + { scope: "!other-emitter", applies: true }, + { scope: "other-emitter", applies: false }, + ])("preserves model metadata scoped to $scope", async ({ scope, applies }) => { + const program = await typeSpecCompile( + ` + @TypeSpec.HttpClient.experimental(#{ + emitterScope: "${scope}", diagnosticId: "MODEL001", dependsOn: #["DEP001"] + }) + model Preview { value: string; } + model Stable { count: int32; } + ${declaration} + model Wrapper { value: ${type}; } + op read(): Wrapper; + `, + runner, + { IsHttpClientNeeded: true }, + ); + expectDiagnosticEmpty(program.diagnostics); + const sdkContext = await createCSharpSdkContext(createEmitterContext(program)); + const [root, diagnostics] = createModel(sdkContext); + expectDiagnosticEmpty(diagnostics); + const preview = root.models.find((model) => model.name === "Preview"); + const wrapper = root.models.find((model) => model.name === "Wrapper"); + ok(preview); + ok(wrapper); + deepStrictEqual( + preview.experimental, + applies ? { diagnosticId: "MODEL001", dependsOn: ["DEP001"] } : undefined, + ); + strictEqual(wrapper.experimental, undefined); + strictEqual(wrapper.properties[0].experimental, undefined); + strictEqual(wrapper.properties[0].type.experimental, undefined); + }); + }); + + it.each([ + `@TypeSpec.HttpClient.experimental(#{ diagnosticId: "SCALAR001" }) + scalar CustomString extends string; op read(): CustomString;`, + `op read(@TypeSpec.HttpClient.experimental(#{ diagnosticId: "PARAM001" }) + @query value: string): void;`, + `@TypeSpec.HttpClient.experimental(#{ diagnosticId: "UNION001" }) + union Choice { text: string, count: int32 } op read(): Choice;`, + `union Choice { + @TypeSpec.HttpClient.experimental(#{ diagnosticId: "VARIANT001" }) + text: string, count: int32 + } op read(): Choice;`, + `model Preview { value: string; } + model Stable { count: int32; } + union Choice { + @TypeSpec.HttpClient.experimental(#{ diagnosticId: "VARIANT001" }) + preview: Preview, stable: Stable + } + model Wrapper { value: Choice; } + op read(): Wrapper;`, + `@TypeSpec.HttpClient.experimental(#{ diagnosticId: "MODEL001" }) + model Preview { value: string; } + model Stable { count: int32; } + union Choice { + @TypeSpec.HttpClient.experimental(#{ diagnosticId: "VARIANT001" }) + preview: Preview, stable: Stable + } + model Wrapper { value: Choice; } + op read(): Wrapper;`, + `model Preview { value: string; } + union Choice { + @TypeSpec.HttpClient.experimental(#{ diagnosticId: "VARIANT001" }) + preview: Preview, null + } + model Wrapper { value: Choice; } + op read(): Wrapper;`, + ])("reports annotations with no supported C# declaration", async (code) => { + const program = await typeSpecCompile(code, runner, { IsHttpClientNeeded: true }); + const sdkContext = await createCSharpSdkContext(createEmitterContext(program)); + const [, diagnostics] = createModel(sdkContext); + expectDiagnostics(diagnostics, { + code: "@typespec/http-client-csharp/experimental-target-not-supported", + }); + }); + + it.each([ + { scope: undefined, applies: true }, + { scope: "@typespec/http-client-csharp", applies: true }, + { scope: "other-emitter, @typespec/http-client-csharp", applies: true }, + { scope: "other-emitter", applies: false }, + { scope: "!other-emitter", applies: true }, + { scope: "!@typespec/http-client-csharp", applies: false }, + { scope: "!other-emitter, !@typespec/http-client-csharp", applies: false }, + ])("respects emitter scope $scope", async ({ scope, applies }) => { + const program = await typeSpecCompile( + ` + @TypeSpec.HttpClient.experimental(#{ + ${scope === undefined ? "" : `emitterScope: "${scope}",`} + diagnosticId: "C", + dependsOn: #["A", "B"] + }) + op bar(): void; + `, + runner, + { IsHttpClientNeeded: true }, + ); + expectDiagnosticEmpty(program.diagnostics); + const sdkContext = await createCSharpSdkContext(createEmitterContext(program), { + additionalDecorators: [], + }); + expectDiagnosticEmpty(sdkContext.diagnostics); + const [root, diagnostics] = createModel(sdkContext); + expectDiagnosticEmpty(diagnostics); + deepStrictEqual( + root.clients[0].methods[0].operation.experimental, + applies ? { diagnosticId: "C", dependsOn: ["A", "B"] } : undefined, + ); + }); + + it.each([ + { decorator: "", expected: undefined }, + { + decorator: "@TypeSpec.HttpClient.experimental", + expected: { diagnosticId: undefined, dependsOn: [] }, + }, + { + decorator: '@TypeSpec.HttpClient.experimental(#{ diagnosticId: "C" })', + expected: { diagnosticId: "C", dependsOn: [] }, + }, + { + decorator: '@TypeSpec.HttpClient.experimental(#{ dependsOn: #["A"] })', + expected: { diagnosticId: undefined, dependsOn: ["A"] }, + }, + { + decorator: '@TypeSpec.HttpClient.experimental(#{ diagnosticId: "C", dependsOn: #[] })', + expected: { diagnosticId: "C", dependsOn: [] }, + }, + ])("preserves optional metadata for $decorator", async ({ decorator, expected }) => { + const program = await typeSpecCompile(`${decorator} op bar(): void;`, runner, { + IsHttpClientNeeded: true, + }); + expectDiagnosticEmpty(program.diagnostics); + const sdkContext = await createCSharpSdkContext(createEmitterContext(program)); + const [root, diagnostics] = createModel(sdkContext); + expectDiagnosticEmpty(diagnostics); + deepStrictEqual(root.clients[0].methods[0].operation.experimental, expected); + }); + }); + it("emit decorator list on a client", async () => { const program = await typeSpecCompile( ` diff --git a/packages/http-client-csharp/emitter/test/Unit/type-converter.test.ts b/packages/http-client-csharp/emitter/test/Unit/type-converter.test.ts index 7c399bdd299..75305bc59e8 100644 --- a/packages/http-client-csharp/emitter/test/Unit/type-converter.test.ts +++ b/packages/http-client-csharp/emitter/test/Unit/type-converter.test.ts @@ -1,8 +1,13 @@ vi.resetModules(); import type { DecoratorInfo } from "@azure-tools/typespec-client-generator-core"; -import type { TestHost } from "@typespec/compiler/testing"; -import { ok, strictEqual } from "assert"; +import { + expectDiagnosticEmpty, + expectDiagnostics, + type TestHost, +} from "@typespec/compiler/testing"; +import { HttpClientTestLibrary } from "@typespec/http-client/testing"; +import { deepStrictEqual, ok, strictEqual } from "assert"; import { beforeEach, describe, it, vi } from "vitest"; import { createModel } from "../../src/lib/client-model-builder.js"; import { getAllModelDecorators } from "../../src/lib/type-converter.js"; @@ -93,6 +98,54 @@ describe("External types", () => { beforeEach(async () => { runner = await createEmitterTestHost(); + await runner.addTypeSpecLibrary(HttpClientTestLibrary); + }); + + describe.each([ + { kind: "model", declaration: "model ExternalValue { value: string; }" }, + { kind: "enum", declaration: 'enum ExternalValue { One: "one", Two: "two" }' }, + { kind: "union", declaration: "union ExternalValue { text: string, count: int32 }" }, + { kind: "scalar", declaration: "scalar ExternalValue extends string;" }, + { kind: "nullable", declaration: "union ExternalValue { string, null }" }, + { kind: "array", declaration: "model ExternalValue is Array;" }, + { kind: "dict", declaration: "model ExternalValue is Record;" }, + { kind: "utcDateTime", declaration: "scalar ExternalValue extends utcDateTime;" }, + { kind: "duration", declaration: "scalar ExternalValue extends duration;" }, + ])("experimental external $kind", ({ declaration, kind }) => { + it.each([ + { scope: "@typespec/http-client-csharp", applies: true }, + { scope: "!other-emitter", applies: true }, + { scope: "other-emitter", applies: false }, + ])("preserves metadata scoped to $scope", async ({ scope, applies }) => { + const program = await typeSpecCompile( + ` + @TypeSpec.HttpClient.experimental(#{ + emitterScope: "${scope}", diagnosticId: "EXTERNAL001", dependsOn: #["DEP001"] + }) + @alternateType({ identity: "External.Value" }, "csharp") + ${declaration} + model Wrapper { value: ExternalValue; } + op read(): Wrapper; + `, + runner, + { IsTCGCNeeded: true, IsHttpClientNeeded: true }, + ); + const sdkContext = await createCSharpSdkContext(createEmitterContext(program)); + expectDiagnostics( + sdkContext.diagnostics, + kind === "union" + ? [{ code: "@azure-tools/typespec-azure-core/union-enums-multiple-kind" }] + : [], + ); + const [root, diagnostics] = createModel(sdkContext); + expectDiagnosticEmpty(diagnostics); + const type = root.models.find((model) => model.name === "Wrapper")!.properties[0].type; + strictEqual(type.external?.identity, "External.Value"); + deepStrictEqual( + type.experimental, + applies ? { diagnosticId: "EXTERNAL001", dependsOn: ["DEP001"] } : undefined, + ); + }); }); it("should convert external type from @alternateType decorator", async () => { diff --git a/packages/http-client-csharp/emitter/test/Unit/utils/test-util.ts b/packages/http-client-csharp/emitter/test/Unit/utils/test-util.ts index 59e17d91097..1c406eb10da 100644 --- a/packages/http-client-csharp/emitter/test/Unit/utils/test-util.ts +++ b/packages/http-client-csharp/emitter/test/Unit/utils/test-util.ts @@ -52,6 +52,7 @@ export interface TypeSpecCompileOptions { NoEmit?: boolean; IsVersionNeeded?: boolean; IsSseNeeded?: boolean; + IsHttpClientNeeded?: boolean; } export async function typeSpecCompile( @@ -85,6 +86,7 @@ export async function typeSpecCompile( const fileContent = ` import "@typespec/rest"; import "@typespec/http"; + ${options?.IsHttpClientNeeded ? 'import "@typespec/http-client";' : ""} import "@typespec/http/streams"; ${needSse ? 'import "@typespec/events";\nimport "@typespec/sse";' : ""} import "@typespec/versioning"; diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientOptionsProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientOptionsProvider.cs index c62e74461fd..7ef2036ae6d 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientOptionsProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientOptionsProvider.cs @@ -26,6 +26,9 @@ public class ClientOptionsProvider : TypeProvider private const string LatestVersionFieldName = $"{LatestPrefix}{VersionSuffix}"; private readonly InputClient _inputClient; + protected override SuppressionStatement[] BuildDisabledFileWarnings() + => ExperimentalApiHelpers.GetParameterSuppressions(_inputClient.Parameters); + private readonly ClientProvider _clientProvider; private readonly Lazy?> _serviceVersionsEnums; private static ClientOptionsProvider? _singletonInstance; diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientProvider.cs index d35fbaa8cf8..04b7dfa40c7 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientProvider.cs @@ -46,6 +46,14 @@ private record ApiVersionFields(FieldProvider Field, PropertyProvider? Correspon private readonly FormattableString _publicCtorDescription; private readonly InputClient _inputClient; internal InputClient InputClient => _inputClient; + protected override IReadOnlyList BuildAttributes() + => CustomCodeView?.Attributes.Any(a => a.Type.Equals(typeof(ExperimentalAttribute))) == true + ? [] + : ExperimentalApiHelpers.BuildAttributes(_inputClient.Experimental); + + protected override SuppressionStatement[] BuildDisabledFileWarnings() + => ExperimentalApiHelpers.GetSuppressions(_inputClient); + private readonly InputAuth? _inputAuth; private readonly ParameterProvider _endpointParameter; private readonly ParameterProvider _subClientEndpointParameter; diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientSettingsProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientSettingsProvider.cs index ed69046abb1..faa4a3615c3 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientSettingsProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientSettingsProvider.cs @@ -16,6 +16,7 @@ using Microsoft.TypeSpec.Generator.Snippets; using Microsoft.TypeSpec.Generator.Statements; using Microsoft.TypeSpec.Generator.ClientModel.Utilities; +using Microsoft.TypeSpec.Generator.Utilities; using static Microsoft.TypeSpec.Generator.Snippets.Snippet; namespace Microsoft.TypeSpec.Generator.ClientModel.Providers @@ -25,6 +26,9 @@ public class ClientSettingsProvider : TypeProvider internal const string ClientSettingsDiagnosticId = "SCME0002"; private readonly ClientProvider _clientProvider; + protected override SuppressionStatement[] BuildDisabledFileWarnings() + => ExperimentalApiHelpers.GetParameterSuppressions(_clientProvider.InputClient.Parameters); + private readonly HashSet _reportedUnsupportedCustomParameters = []; #pragma warning disable SCME0002 // ClientSettings is for evaluation purposes only diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/CollectionResultDefinition.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/CollectionResultDefinition.cs index c6dde93b551..c2f994d2c70 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/CollectionResultDefinition.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/CollectionResultDefinition.cs @@ -18,6 +18,7 @@ using Microsoft.TypeSpec.Generator.Providers; using Microsoft.TypeSpec.Generator.Snippets; using Microsoft.TypeSpec.Generator.Statements; +using Microsoft.TypeSpec.Generator.Utilities; using static Microsoft.TypeSpec.Generator.Snippets.Snippet; namespace Microsoft.TypeSpec.Generator.ClientModel.Providers @@ -184,6 +185,11 @@ private PropertyProvider FindPropertyInModelHierarchy(TypeProvider model, string protected override string BuildNamespace() => Client.Type.Namespace; + protected override SuppressionStatement[] BuildDisabledFileWarnings() + => ExperimentalApiHelpers.MergeSuppressions( + ResponseModel.DisabledFileWarnings, + ExperimentalApiHelpers.GetSuppressions(Operation, Client.InputClient)); + protected override string BuildName() { var operationName = Operation.Name.ToIdentifierName(); diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs index 5582271546c..714fede391e 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/RestClientProvider.cs @@ -52,6 +52,9 @@ public RestClientProvider(InputClient inputClient, ClientProvider clientProvider public ClientProvider ClientProvider { get; } + protected override SuppressionStatement[] BuildDisabledFileWarnings() + => ExperimentalApiHelpers.GetSuppressions(_inputClient); + protected override string BuildRelativeFilePath() => Path.Combine("src", "Generated", $"{Name}.RestClient.cs"); protected override string BuildName() => ClientProvider.Name; @@ -245,13 +248,15 @@ private ScmMethodProvider BuildCreateRequestMethod(InputServiceMethod serviceMet // Build message and all request modifications var messageStatements = BuildMessage(serviceMethod, signature, isNextLinkRequest); - return new ScmMethodProvider( + var method = new ScmMethodProvider( signature, messageStatements, this, ScmMethodKind.CreateRequest, xmlDocProvider: XmlDocProvider.Empty, serviceMethod: serviceMethod); + ExperimentalApiHelpers.AddDependencySuppressions(method, serviceMethod.Operation); + return method; } private MethodBodyStatements BuildMessage( diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs index aba81a66377..fb875eb85e0 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmMethodProviderCollection.cs @@ -215,10 +215,11 @@ private ScmMethodProvider BuildConvenienceMethod(MethodProvider protocolMethod, GetConvenienceMethodModifiers(protocolMethod.Signature.Modifiers, signatureParameters), GetResponseType(ServiceMethod.Operation.Responses, true, isAsync, out _), null, - signatureParameters, - Attributes: BuildConvenienceMethodAttributes()); + signatureParameters); } + ApplyExperimentalAttributes(methodSignature, customSignature, BuildConvenienceMethodAttributes() ?? []); + // Recompute the response body type so we can branch the body accordingly. GetResponseType(ServiceMethod.Operation.Responses, true, isAsync, out var responseBodyType); var streamingResponse = _streamingResponse.Value; @@ -302,6 +303,7 @@ .. GetStackVariablesForReturnValueConversion(result, responseBodyType, isAsync, } var convenienceMethod = new ScmMethodProvider(methodSignature, methodBody, EnclosingType, ScmMethodKind.Convenience, collectionDefinition: collection, serviceMethod: ServiceMethod); + ExperimentalApiHelpers.AddDependencySuppressions(convenienceMethod, ServiceMethod.Operation); if (convenienceMethod.XmlDocs != null) { @@ -1121,6 +1123,11 @@ private static bool IsConvertibleFromBinaryData(CSharpType type) private IReadOnlyList? BuildConvenienceMethodAttributes() { + if (ExperimentalApiHelpers.BuildAttribute(ServiceMethod.Operation) is { } experimentalAttribute) + { + return [experimentalAttribute]; + } + var bodyInputParam = ServiceMethod.Parameters.FirstOrDefault(p => p.Location == InputRequestLocation.Body); if (bodyInputParam?.Type is InputModelType bodyModel && bodyModel.Usage.HasFlag(InputModelTypeUsage.MultipartFormData)) @@ -1131,6 +1138,22 @@ private static bool IsConvertibleFromBinaryData(CSharpType type) return null; } + private static void ApplyExperimentalAttributes( + MethodSignature signature, + MethodSignature? customSignature, + IReadOnlyList generatedAttributes) + { + if (customSignature?.Attributes.Any(a => a.Type.Equals(typeof(ExperimentalAttribute))) == true) + { + // The defining partial declaration already carries the custom experiment. + signature.Update(attributes: [.. signature.Attributes.Where(a => !a.Type.Equals(typeof(ExperimentalAttribute)))]); + } + else if (generatedAttributes.Count > 0) + { + signature.Update(attributes: [.. signature.Attributes, .. generatedAttributes]); + } + } + private IReadOnlyList GetProtocolMethodArguments(Dictionary declarations) { List conversions = new List(); @@ -1441,6 +1464,8 @@ private ScmMethodProvider BuildProtocolMethod(MethodProvider createRequestMethod bodyParameters = parameters; } + ApplyExperimentalAttributes(methodSignature, customSignature, ExperimentalApiHelpers.BuildAttributes(ServiceMethod.Operation.Experimental)); + TypeProvider? collection = null; MethodBodyStatement[] methodBody; if (_pagingServiceMethod != null) @@ -1478,6 +1503,7 @@ .. ServiceMethod.Operation.BufferResponse var protocolMethod = new ScmMethodProvider(methodSignature, methodBody, EnclosingType, ScmMethodKind.Protocol, collectionDefinition: collection, serviceMethod: ServiceMethod); + ExperimentalApiHelpers.AddDependencySuppressions(protocolMethod, ServiceMethod.Operation); if (protocolMethod.XmlDocs != null) { diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmModelFactoryProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmModelFactoryProvider.cs index 2e2ff07b213..02dd7e29d8c 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmModelFactoryProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmModelFactoryProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Linq; using Microsoft.TypeSpec.Generator.Input; using Microsoft.TypeSpec.Generator.Providers; using Microsoft.TypeSpec.Generator.Statements; @@ -31,7 +32,8 @@ protected override MethodProvider[] BuildMethods() foreach (var method in methods) { - if (!MethodReferencesFileBinaryContent(method)) + if (!MethodReferencesFileBinaryContent(method) + || method.Signature.Attributes.Any(a => a.Type.Equals(typeof(ExperimentalAttribute)))) { continue; } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmModelProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmModelProvider.cs index 660f0cdd3cf..95972f46508 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmModelProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmModelProvider.cs @@ -117,7 +117,8 @@ protected override PropertyProvider[] BuildProperties() foreach (var prop in properties) { - if (IsFileBinaryContentType(prop.Type)) + if (IsFileBinaryContentType(prop.Type) + && !prop.Attributes.Any(a => a.Type.Equals(typeof(ExperimentalAttribute)))) { prop.Update(attributes: [.. prop.Attributes, new AttributeStatement(typeof(ExperimentalAttribute), [Literal(FileBinaryContentDiagnosticId)])]); } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ClientProviders/ClientProviderTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ClientProviders/ClientProviderTests.cs index 26a8e45fd8e..84dc616fd71 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ClientProviders/ClientProviderTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ClientProviders/ClientProviderTests.cs @@ -5,12 +5,15 @@ using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Xml.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.TypeSpec.Generator.ClientModel.Providers; using Microsoft.TypeSpec.Generator.Expressions; using Microsoft.TypeSpec.Generator.Input; @@ -25,6 +28,71 @@ namespace Microsoft.TypeSpec.Generator.ClientModel.Tests.Providers.ClientProvide { public class ClientProviderTests { + [Test] + public void ExperimentalChildParametersAreSuppressedOnParentAccessors() + { + var mode = InputFactory.Experimental(InputFactory.StringEnum("Mode", [("One", "one")], isExtensible: true), "MODE001"); + var parent = InputFactory.Client("ParentClient"); + var child = InputFactory.Client("ChildClient", parent: parent, + parameters: [InputFactory.PathParameter("mode", mode, isRequired: true, scope: InputParameterScope.Client)], + initializedBy: InputClientInitializedBy.Parent); + MockHelpers.LoadMockGenerator(inputEnums: () => [mode], clients: () => [parent, child]); + var generator = ScmCodeModelGenerator.Instance; + var client = generator.TypeFactory.CreateClient(parent)!; + var accessor = client.Methods.Single(m => m.Signature.Name == "GetChildClient"); + Assert.AreEqual("Mode", accessor.Signature.Parameters.Single().Type.Name); + Assert.IsTrue(client.DisabledFileWarnings.Any(s => s.Code.ToDisplayString() == Literal("MODE001").ToDisplayString())); + + var references = AppDomain.CurrentDomain.GetAssemblies() + .Where(a => !a.IsDynamic && !string.IsNullOrEmpty(a.Location)) + .Select(a => MetadataReference.CreateFromFile(a.Location)) + .Append(MetadataReference.CreateFromFile(typeof(Microsoft.Extensions.Configuration.IConfigurationSection).Assembly.Location)); + var providers = generator.OutputLibrary.TypeProviders + .Where(p => p is not Utf8JsonBinaryContentDefinition and not BinaryContentHelperDefinition); + var compilation = CSharpCompilation.Create( + "ExperimentalChildParameters", + providers.Select(p => CSharpSyntaxTree.ParseText(new TypeProviderWriter(p).Write().Content)), + references, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, generalDiagnosticOption: ReportDiagnostic.Error)); + Assert.IsEmpty(compilation.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error).Select(d => d.ToString())); + } + + [Test] + public async Task ExperimentalCustomClientKeepsExistingAttribute() + { + var input = InputFactory.Experimental(InputFactory.Client("TestClient"), "GENERATED001"); + await MockHelpers.LoadMockGeneratorAsync( + clients: () => [input], + compilation: async () => await Helpers.GetCompilationFromDirectoryAsync()); + var client = ScmCodeModelGenerator.Instance.TypeFactory.CreateClient(input)!; + + Assert.AreEqual(0, client.Attributes.Count(a => a.Type.Equals(typeof(ExperimentalAttribute)))); + Assert.AreEqual(Literal("CUSTOM001").ToDisplayString(), + client.CanonicalView.Attributes.Single(a => a.Type.Equals(typeof(ExperimentalAttribute))).Arguments[0].ToDisplayString()); + } + + [Test] + public void ExperimentalClientAndModelReferences() + { + var model = InputFactory.Experimental(InputFactory.Model("Payload"), "MODEL001"); + var operation = InputFactory.Operation("Read", responses: [InputFactory.OperationResponse(bodytype: model)]); + var clientInput = InputFactory.Experimental( + InputFactory.Client("Experiment", methods: [InputFactory.BasicServiceMethod("Read", operation)]), + "CLIENT001", "DEP001"); + MockHelpers.LoadMockGenerator(inputModels: () => [model], clients: () => [clientInput]); + var client = ScmCodeModelGenerator.Instance.TypeFactory.CreateClient(clientInput)!; + + Assert.AreEqual(Literal("CLIENT001").ToDisplayString(), + client.Attributes.Single(a => a.Type.Equals(typeof(ExperimentalAttribute))).Arguments[0].ToDisplayString()); + foreach (var provider in new TypeProvider[] { client, client.RestClient }) + { + CollectionAssert.IsSubsetOf( + new[] { "CLIENT001", "DEP001", "MODEL001" }.Select(id => Literal(id).ToDisplayString()), + provider.DisabledFileWarnings.Select(s => s.Code.ToDisplayString())); + } + Assert.IsFalse(client.RestClient.Attributes.Any(a => a.Type.Equals(typeof(ExperimentalAttribute)))); + } + [TestCase("Foo", "Foo", ExpectedResult = true)] [TestCase("Foo", "Bar", ExpectedResult = false)] [TestCase("Foo", "_Foo", ExpectedResult = false)] diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ClientProviders/TestData/ClientProviderTests/ExperimentalCustomClientKeepsExistingAttribute/TestClient.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ClientProviders/TestData/ClientProviderTests/ExperimentalCustomClientKeepsExistingAttribute/TestClient.cs new file mode 100644 index 00000000000..967d62aa4a5 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ClientProviders/TestData/ClientProviderTests/ExperimentalCustomClientKeepsExistingAttribute/TestClient.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Diagnostics.CodeAnalysis; + +namespace Sample +{ + [Experimental("CUSTOM001")] + public partial class TestClient + { + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ClientSettingsProviderTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ClientSettingsProviderTests.cs index b9655612614..5d639611527 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ClientSettingsProviderTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ClientSettingsProviderTests.cs @@ -7,11 +7,14 @@ using System.Linq; using System.Reflection; using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.TypeSpec.Generator.EmitterRpc; using Microsoft.TypeSpec.Generator.ClientModel.Providers; using Microsoft.TypeSpec.Generator.Input; using Microsoft.TypeSpec.Generator.Primitives; using Microsoft.TypeSpec.Generator.Providers; +using Microsoft.TypeSpec.Generator.Snippets; using Microsoft.TypeSpec.Generator.Statements; using Microsoft.TypeSpec.Generator.Tests.Common; using NUnit.Framework; @@ -20,6 +23,38 @@ namespace Microsoft.TypeSpec.Generator.ClientModel.Tests.Providers { public class ClientSettingsProviderTests { + [Test] + public void ExperimentalClientParametersCompileInOptionsAndSettings() + { + var mode = InputFactory.Experimental(InputFactory.StringEnum("Mode", [("One", "one")], isExtensible: true), "MODE001"); + var input = InputFactory.Client("TestClient", parameters: + [ + InputFactory.MethodParameter("requiredMode", mode, isRequired: true, scope: InputParameterScope.Client), + InputFactory.MethodParameter("optionalMode", mode, defaultValue: new InputConstant("one", mode), scope: InputParameterScope.Client) + ]); + MockHelpers.LoadMockGenerator(inputEnums: () => [mode], clients: () => [input]); + var client = ScmCodeModelGenerator.Instance.TypeFactory.CreateClient(input)!; + var enumProvider = ScmCodeModelGenerator.Instance.TypeFactory.CreateEnum(mode)!; + var options = client.ClientOptions!; + var settings = client.ClientSettings!; + var references = AppDomain.CurrentDomain.GetAssemblies() + .Where(a => !a.IsDynamic && !string.IsNullOrEmpty(a.Location)) + .Select(a => MetadataReference.CreateFromFile(a.Location)) + .Append(MetadataReference.CreateFromFile(typeof(Microsoft.Extensions.Configuration.IConfigurationSection).Assembly.Location)); + var compilation = CSharpCompilation.Create( + "ExperimentalClientParameters", + new TypeProvider[] { enumProvider, options, settings, new ArgumentDefinition() } + .Select(p => CSharpSyntaxTree.ParseText(new TypeProviderWriter(p).Write().Content)), + references, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, generalDiagnosticOption: ReportDiagnostic.Error)); + var errors = compilation.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.IsEmpty(errors.Select(d => d.ToString())); + foreach (var provider in new TypeProvider[] { options, settings }) + { + Assert.IsTrue(provider.DisabledFileWarnings.Any(s => s.Code.ToDisplayString() == Snippet.Literal("MODE001").ToDisplayString())); + } + } + [SetUp] public void SetUp() { diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/CollectionResultDefinitions/CollectionResultDefinitionTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/CollectionResultDefinitions/CollectionResultDefinitionTests.cs index f76c1e3c87a..9d40ed4f8c5 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/CollectionResultDefinitions/CollectionResultDefinitionTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/CollectionResultDefinitions/CollectionResultDefinitionTests.cs @@ -6,6 +6,7 @@ using Microsoft.TypeSpec.Generator.ClientModel.Providers; using Microsoft.TypeSpec.Generator.Input; using Microsoft.TypeSpec.Generator.Primitives; +using Microsoft.TypeSpec.Generator.Snippets; using Microsoft.TypeSpec.Generator.Tests.Common; using NUnit.Framework; @@ -13,6 +14,27 @@ namespace Microsoft.TypeSpec.Generator.ClientModel.Tests.Providers.CollectionRes { public class CollectionResultDefinitionTests { + [Test] + public void ExperimentalPagingDependenciesAreSuppressedInAllHelpers() + { + var item = InputFactory.Experimental(InputFactory.Model("Item"), "ITEM001"); + var envelope = InputFactory.Model("Page", properties: [InputFactory.Property("items", InputFactory.Array(item))]); + var operation = InputFactory.Operation("List", responses: [InputFactory.OperationResponse(bodytype: envelope)]); + operation.Update(experimental: new InputExperimentalDetails("API001", ["DEPENDENCY001"])); + var serviceMethod = InputFactory.PagingServiceMethod("List", operation, pagingMetadata: InputFactory.PagingMetadata(["items"], null, null)); + var client = InputFactory.Experimental(InputFactory.Client("TestClient", methods: [serviceMethod]), "CLIENT001"); + MockHelpers.LoadMockGenerator(inputModels: () => [item, envelope], clients: () => [client]); + var helpers = ScmCodeModelGenerator.Instance.OutputLibrary.TypeProviders.OfType().ToArray(); + + Assert.AreEqual(4, helpers.Length); + foreach (var helper in helpers) + { + CollectionAssert.IsSubsetOf( + new[] { "ITEM001", "CLIENT001", "API001", "DEPENDENCY001" }.Select(id => Snippet.Literal(id).ToDisplayString()), + helper.DisabledFileWarnings.Select(s => s.Code.ToDisplayString())); + } + } + [SetUp] public void Setup() { diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ModelFactoryProviders/ScmModelFactoryProviderTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ModelFactoryProviders/ScmModelFactoryProviderTests.cs index 8ca50191b93..14e7e47cf26 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ModelFactoryProviders/ScmModelFactoryProviderTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ModelFactoryProviders/ScmModelFactoryProviderTests.cs @@ -3,12 +3,18 @@ #pragma warning disable SCME0004 // FileBinaryContent is evaluation-only. +using System; using System.ClientModel; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.TypeSpec.Generator.Input; using Microsoft.TypeSpec.Generator.Primitives; +using Microsoft.TypeSpec.Generator.Providers; +using Microsoft.TypeSpec.Generator.Snippets; using Microsoft.TypeSpec.Generator.Tests.Common; using NUnit.Framework; @@ -16,6 +22,136 @@ namespace Microsoft.TypeSpec.Generator.ClientModel.Tests.Providers.ModelFactoryP { public class ScmModelFactoryProviderTests { + [Test] + public void ExperimentalExternalTypesOnlyContributeReferenceSuppressions() + { + var externalModel = InputFactory.Experimental( + InputFactory.Model("ForeignPatch", properties: [], + external: new InputExternalTypeMetadata("System.ClientModel.Primitives.JsonPatch", null, null)), + "SCME0001"); + var externalEnum = InputFactory.Experimental( + InputFactory.StringEnum("ForeignStatus", [("OK", "OK")], + external: new InputExternalTypeMetadata("System.Net.HttpStatusCode", null, null)), + "EXTERNAL_ENUM"); + var input = InputFactory.Model("Payload", properties: [InputFactory.Property("patch", externalModel)]); + MockHelpers.LoadMockGenerator(inputModels: () => [externalModel, input], inputEnums: () => [externalEnum]); + var generator = ScmCodeModelGenerator.Instance; + var model = generator.TypeFactory.CreateModel(input)!; + var factory = generator.TypeFactory.CreateModelFactory([externalModel, input]); + + Assert.IsInstanceOf(generator.TypeFactory.CreateModel(externalModel)); + Assert.IsNull(generator.TypeFactory.CreateEnum(externalEnum)); + Assert.IsFalse(generator.OutputLibrary.TypeProviders.Any(p => p is SystemObjectModelProvider || p.Name == "ForeignStatus")); + Assert.AreEqual("Payload", factory.Methods.Single().Signature.Name); + Assert.IsFalse(model.Attributes.Any(a => a.Type.Equals(typeof(ExperimentalAttribute)))); + Assert.IsFalse(factory.Methods.Single().Signature.Attributes.Any(a => a.Type.Equals(typeof(ExperimentalAttribute)))); + Assert.IsTrue(model.DisabledFileWarnings.Any(s => s.Code.ToDisplayString() == Snippet.Literal("SCME0001").ToDisplayString())); + + var references = AppDomain.CurrentDomain.GetAssemblies() + .Where(a => !a.IsDynamic && !string.IsNullOrEmpty(a.Location)) + .Select(a => MetadataReference.CreateFromFile(a.Location)); + var compilation = CSharpCompilation.Create( + "ExperimentalExternalReferences", + new TypeProvider[] { model, factory, new ArgumentDefinition() } + .Select(p => CSharpSyntaxTree.ParseText(new TypeProviderWriter(p).Write().Content)), + references, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, generalDiagnosticOption: ReportDiagnostic.Error)); + Assert.IsEmpty(compilation.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error).Select(d => d.ToString())); + } + + [TestCase(false)] + [TestCase(true)] + public async Task ExperimentalLiteralEnumMembersCompileInModelsAndFactories(bool extensible) + { + var choice = InputFactory.StringEnum("Choice", [("One", "one"), ("Two", "two")], isExtensible: extensible); + InputFactory.Experimental(choice.Values[0], "SAMPLE_MEMBER"); + InputFactory.Experimental(choice.Values[1], "OTHER_MEMBER"); + var input = InputFactory.Model("Payload", properties: + [InputFactory.Property("kind", choice.Values[0], isRequired: true)]); + Compilation? customCompilation = null; + await MockHelpers.LoadMockGeneratorAsync( + inputEnums: () => [choice], inputModels: () => [input], + compilation: extensible ? null : async () => customCompilation = await Helpers.GetCompilationFromDirectoryAsync()); + var generator = ScmCodeModelGenerator.Instance; + var model = generator.TypeFactory.CreateModel(input)!; + var factory = generator.TypeFactory.CreateModelFactory([input]); + var enumProvider = generator.TypeFactory.CreateEnum(choice)!; + + Assert.IsFalse(enumProvider.Attributes.Any(a => a.Type.Equals(typeof(ExperimentalAttribute)))); + foreach (var provider in new TypeProvider[] { model, factory }) + { + CollectionAssert.AreEqual( + new[] { Snippet.Literal("SAMPLE_MEMBER").ToDisplayString() }, + provider.DisabledFileWarnings.Select(s => s.Code.ToDisplayString())); + } + var references = AppDomain.CurrentDomain.GetAssemblies() + .Where(a => !a.IsDynamic && !string.IsNullOrEmpty(a.Location)) + .Select(a => MetadataReference.CreateFromFile(a.Location)); + var compilation = CSharpCompilation.Create( + "ExperimentalLiteralEnum", + new TypeProvider[] { model, factory, new ArgumentDefinition() } + .Select(p => CSharpSyntaxTree.ParseText(new TypeProviderWriter(p).Write().Content)) + .Concat(extensible + ? new[] { CSharpSyntaxTree.ParseText(new TypeProviderWriter(enumProvider).Write().Content) } + : customCompilation!.SyntaxTrees.Where(t => t.FilePath.EndsWith("CustomTypes.cs", StringComparison.Ordinal))), + references, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, generalDiagnosticOption: ReportDiagnostic.Error)); + Assert.IsEmpty(compilation.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error).Select(d => d.ToString())); + if (!extensible) + { + StringAssert.Contains("Choice.One", factory.Methods.Single().BodyStatements!.ToDisplayString()); + } + } + + [TestCase(true, false)] + [TestCase(false, true)] + [TestCase(true, true)] + public void SourceExperimentalMultipartDeclarationsCompile(bool experimentalModel, bool experimentalProperty) + { + var property = FilePartProperty("file"); + if (experimentalProperty) + { + InputFactory.Experimental(property, "PROPERTY001"); + } + var input = MultipartModel("Payload", [property]); + if (experimentalModel) + { + InputFactory.Experimental(input, "MODEL001"); + } + MockHelpers.LoadMockGenerator(inputModels: () => [input]); + var model = ScmCodeModelGenerator.Instance.TypeFactory.CreateModel(input)!; + var factory = ScmCodeModelGenerator.Instance.TypeFactory.CreateModelFactory([input]); + var references = AppDomain.CurrentDomain.GetAssemblies() + .Where(a => !a.IsDynamic && !string.IsNullOrEmpty(a.Location)) + .Select(a => MetadataReference.CreateFromFile(a.Location)); + var compilation = CSharpCompilation.Create( + "ExperimentalMultipart", + [CSharpSyntaxTree.ParseText(new TypeProviderWriter(model).Write().Content), + CSharpSyntaxTree.ParseText(new TypeProviderWriter(factory).Write().Content), + CSharpSyntaxTree.ParseText(new TypeProviderWriter(new ArgumentDefinition()).Write().Content)], + references, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, generalDiagnosticOption: ReportDiagnostic.Error)); + + var errors = compilation.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.IsEmpty(errors.Select(d => d.ToString())); + Assert.AreEqual(Snippet.Literal(experimentalModel ? "MODEL001" : "SCME0004").ToDisplayString(), + factory.Methods.Single().Signature.Attributes.Single(a => a.Type.Equals(typeof(ExperimentalAttribute))).Arguments[0].ToDisplayString()); + Assert.AreEqual(Snippet.Literal(experimentalProperty ? "PROPERTY001" : "SCME0004").ToDisplayString(), + model.Properties.Single(p => p.Name == "File").Attributes.Single(a => a.Type.Equals(typeof(ExperimentalAttribute))).Arguments[0].ToDisplayString()); + } + + [Test] + public void ExperimentalModelFactoryUsesThePublicModelDiagnostic() + { + var input = InputFactory.Experimental(InputFactory.Model("Payload"), "MODEL001", "DEP001"); + MockHelpers.LoadMockGenerator(inputModels: () => [input]); + var factory = ScmCodeModelGenerator.Instance.TypeFactory.CreateModelFactory([input]); + var method = factory.Methods.Single(m => m.Signature.Name == "Payload"); + + Assert.AreEqual(Snippet.Literal("MODEL001").ToDisplayString(), + method.Signature.Attributes.Single(a => a.Type.Equals(typeof(ExperimentalAttribute))).Arguments[0].ToDisplayString()); + } + [SetUp] public void SetUp() { diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ModelFactoryProviders/TestData/ScmModelFactoryProviderTests/ExperimentalLiteralEnumMembersCompileInModelsAndFactories/CustomTypes.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ModelFactoryProviders/TestData/ScmModelFactoryProviderTests/ExperimentalLiteralEnumMembersCompileInModelsAndFactories/CustomTypes.cs new file mode 100644 index 00000000000..6a761b32d82 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ModelFactoryProviders/TestData/ScmModelFactoryProviderTests/ExperimentalLiteralEnumMembersCompileInModelsAndFactories/CustomTypes.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Diagnostics.CodeAnalysis; + +namespace Sample.Models +{ + public partial class Payload + { +#pragma warning disable SAMPLE_MEMBER + public Choice Kind { get; } = Choice.One; +#pragma warning restore SAMPLE_MEMBER + } + + public enum Choice + { + [Experimental("SAMPLE_MEMBER")] + One, + [Experimental("OTHER_MEMBER")] + Two + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmMethodProviderCollectionTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmMethodProviderCollectionTests.cs index a2cab910cda..a9540a0f394 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmMethodProviderCollectionTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmMethodProviderCollectionTests.cs @@ -5,6 +5,7 @@ using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Net.ServerSentEvents; @@ -12,13 +13,18 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.TypeSpec.Generator.ClientModel.Providers; +using Microsoft.TypeSpec.Generator.Utilities; using Microsoft.TypeSpec.Generator.EmitterRpc; +using Microsoft.TypeSpec.Generator.Expressions; using Microsoft.TypeSpec.Generator.Input; using Microsoft.TypeSpec.Generator.Input.Extensions; using Microsoft.TypeSpec.Generator.Primitives; using Microsoft.TypeSpec.Generator.Providers; using Microsoft.TypeSpec.Generator.Snippets; +using Microsoft.TypeSpec.Generator.Statements; using Microsoft.TypeSpec.Generator.Tests.Common; using NUnit.Framework; @@ -34,6 +40,347 @@ internal class ScmMethodProviderCollectionTests InputFactory.Property("p2", InputPrimitiveType.String, isRequired: true), ]); + [TestCase("C", new[] { "A", "B" })] + [TestCase("C", new string[0])] + [TestCase(null, new[] { "A", "B" })] + [TestCase(null, new string[0])] + [TestCase(null, null)] + [TestCase("C", new[] { "A", "A", "B" })] + public void ExperimentalOperationGeneratesScopedDiagnostics(string? diagnosticId, string[]? dependencies) + { + var operation = InputFactory.Operation("Bar"); + operation.Update(experimental: dependencies is null ? null : new InputExperimentalDetails(diagnosticId, dependencies)); + var serviceMethod = InputFactory.BasicServiceMethod("Bar", operation); + var inputClient = InputFactory.Client("TestClient", methods: [serviceMethod]); + MockHelpers.LoadMockGenerator(clients: () => [inputClient]); + var client = ScmCodeModelGenerator.Instance.TypeFactory.CreateClient(inputClient)!; + var methods = new ScmMethodProviderCollection(serviceMethod, client); + + Assert.AreEqual(4, methods.Count); + var expectedDependencies = dependencies?.Distinct().ToArray() ?? []; + foreach (var method in methods.Append(client.RestClient.GetCreateRequestMethod(operation))) + { + var attribute = method.Signature.Attributes.SingleOrDefault(a => a.Type.Equals(typeof(ExperimentalAttribute))); + if (method is ScmMethodProvider { Kind: ScmMethodKind.CreateRequest } || diagnosticId is null) + { + Assert.IsNull(attribute); + } + else + { + Assert.IsNotNull(attribute); + Assert.AreEqual(diagnosticId, ((LiteralExpression)((ScopedApi)attribute!.Arguments.Single()).Original).Literal); + } + + using var writer = new CodeWriter(); + writer.WriteMethod(method); + var code = writer.ToString(false); + var directives = CSharpSyntaxTree.ParseText(code).GetRoot() + .DescendantTrivia(descendIntoTrivia: true) + .Select(t => t.GetStructure()) + .OfType() + .ToArray(); + var disables = directives.Where(d => d.DisableOrRestoreKeyword.IsKind(SyntaxKind.DisableKeyword)).ToArray(); + var restores = directives.Where(d => d.DisableOrRestoreKeyword.IsKind(SyntaxKind.RestoreKeyword)).ToArray(); + CollectionAssert.AreEqual(expectedDependencies, disables.Select(d => d.ErrorCodes.Single().ToString())); + CollectionAssert.AreEqual(expectedDependencies, restores.Select(d => d.ErrorCodes.Single().ToString())); + var declarationStart = code.IndexOf( + method.Signature.Modifiers.HasFlag(MethodSignatureModifiers.Public) ? "public " : "internal ", + StringComparison.Ordinal); + Assert.IsTrue(disables.All(d => d.SpanStart < declarationStart)); + Assert.IsTrue(restores.All(d => d.SpanStart > code.LastIndexOf('}'))); + } + } + + [TestCase("")] + [TestCase(" \t")] + [TestCase("A B")] + [TestCase("A,B")] + [TestCase("A-B")] + [TestCase("A.B")] + [TestCase("1A")] + [TestCase("@A")] + [TestCase("A\n")] + [TestCase("A\r")] + [TestCase("A//B")] + [TestCase("A/*B*/")] + [TestCase("A\n#pragma warning disable")] + public void ExperimentalOperationRejectsInvalidDependencyDiagnostic(string diagnosticId) + { + var operation = InputFactory.Operation("Bar"); + operation.Update(experimental: new InputExperimentalDetails("C", [diagnosticId])); + var serviceMethod = InputFactory.BasicServiceMethod("Bar", operation); + var inputClient = InputFactory.Client("TestClient", methods: [serviceMethod]); + MockHelpers.LoadMockGenerator(clients: () => [inputClient]); + var client = ScmCodeModelGenerator.Instance.TypeFactory.CreateClient(inputClient)!; + + Assert.Throws(() => new ScmMethodProviderCollection(serviceMethod, client)); + } + + [TestCase("A")] + [TestCase("DEP001")] + [TestCase("_DEP001")] + [TestCase("CS0618")] + [TestCase("0618")] + [TestCase("class")] + public void ExperimentalDiagnosticIdProducesOnePragmaToken(string diagnosticId) + { + var operation = InputFactory.Operation("Read"); + operation.Update(experimental: new InputExperimentalDetails("API001", [diagnosticId])); + var method = InputFactory.BasicServiceMethod("Read", operation); + var inputClient = InputFactory.Client("TestClient", methods: [method]); + MockHelpers.LoadMockGenerator(clients: () => [inputClient]); + var client = ScmCodeModelGenerator.Instance.TypeFactory.CreateClient(inputClient)!; + var generatedMethod = new ScmMethodProviderCollection(method, client)[0]; + var tree = CSharpSyntaxTree.ParseText(generatedMethod.Suppressions.Single().DisableStatement.ToDisplayString()); + + Assert.AreEqual(0, tree.GetDiagnostics().Count()); + var pragma = tree.GetRoot().DescendantTrivia(descendIntoTrivia: true).Select(t => t.GetStructure()) + .OfType().Single(); + Assert.AreEqual(diagnosticId, pragma.ErrorCodes.Single().ToString()); + } + + [Test] + public void ExperimentalDependenciesAlreadySuppressedForClientAreNotRestoredByMethods() + { + var model = InputFactory.Experimental(InputFactory.Model("Payload"), "MODEL001"); + var operation = InputFactory.Operation("Read", responses: [InputFactory.OperationResponse(bodytype: model)]); + operation.Update(experimental: new InputExperimentalDetails("API001", ["MODEL001"])); + var method = InputFactory.BasicServiceMethod("Read", operation); + var inputClient = InputFactory.Client("TestClient", methods: [method]); + MockHelpers.LoadMockGenerator(inputModels: () => [model], clients: () => [inputClient]); + var client = ScmCodeModelGenerator.Instance.TypeFactory.CreateClient(inputClient)!; + + foreach (var provider in new ScmMethodProviderCollection(method, client).Append(client.RestClient.GetCreateRequestMethod(operation))) + { + Assert.IsTrue(provider.EnclosingType.DisabledFileWarnings.Any(s => s.Code.ToDisplayString() == Snippet.Literal("MODEL001").ToDisplayString())); + Assert.AreEqual(0, provider.Suppressions.Count, "A method-local restore would undo the generated file's suppression."); + } + } + + [TestCase(null)] + [TestCase("C")] + public void ExperimentalMultipartOperationHasOnePublicDiagnostic(string? diagnosticId) + { + var body = InputFactory.Model("UploadBody", usage: InputModelTypeUsage.Input | InputModelTypeUsage.MultipartFormData); + var operation = InputFactory.Operation("Upload", + parameters: [InputFactory.BodyParameter("body", body, isRequired: true)], + requestMediaTypes: ["multipart/form-data"]); + if (diagnosticId is not null) + { + operation.Update(experimental: new InputExperimentalDetails(diagnosticId, [ClientModel.Providers.ScmModelProvider.FileBinaryContentDiagnosticId])); + } + var serviceMethod = InputFactory.BasicServiceMethod("Upload", operation, + parameters: [InputFactory.MethodParameter("body", body, location: InputRequestLocation.Body, isRequired: true)]); + var inputClient = InputFactory.Client("TestClient", methods: [serviceMethod]); + MockHelpers.LoadMockGenerator(inputModels: () => [body], clients: () => [inputClient]); + var client = ScmCodeModelGenerator.Instance.TypeFactory.CreateClient(inputClient)!; + var methods = new ScmMethodProviderCollection(serviceMethod, client); + + Assert.AreEqual(2, methods.Count(m => m.Kind == ScmMethodKind.Convenience)); + foreach (var method in methods.Where(m => m.Kind == ScmMethodKind.Convenience)) + { + var attribute = method.Signature.Attributes.Single(a => a.Type.Equals(typeof(ExperimentalAttribute))); + Assert.AreEqual(diagnosticId ?? ClientModel.Providers.ScmModelProvider.FileBinaryContentDiagnosticId, + ((LiteralExpression)((ScopedApi)attribute.Arguments.Single()).Original).Literal); + } + } + + [Test] + public async Task ExperimentalOperationSupportsPartialMethods() + { + var operation = InputFactory.Operation("Bar"); + operation.Update(experimental: new InputExperimentalDetails("C", ["A", "B"])); + var serviceMethod = InputFactory.BasicServiceMethod("Bar", operation); + var inputClient = InputFactory.Client("TestClient", methods: [serviceMethod]); + await MockHelpers.LoadMockGeneratorAsync( + clients: () => [inputClient], + compilation: async () => await Helpers.GetCompilationFromDirectoryAsync()); + var client = ScmCodeModelGenerator.Instance.TypeFactory.CreateClient(inputClient)!; + var methods = new ScmMethodProviderCollection(serviceMethod, client); + + Assert.AreEqual(4, methods.Count); + foreach (var method in methods) + { + Assert.IsTrue(method.IsPartialMethod); + var attribute = method.Signature.Attributes.Single(a => a.Type.Equals(typeof(ExperimentalAttribute))); + Assert.AreEqual("C", ((LiteralExpression)((ScopedApi)attribute.Arguments.Single()).Original).Literal); + Assert.AreEqual(2, method.Suppressions.Count); + } + } + + [TestCase("plain", false, true, null)] + [TestCase("generic", false, true, null)] + [TestCase("array", false, true, null)] + [TestCase("nested", false, true, null)] + [TestCase("plain", true, true, null)] + [TestCase("plain", false, false, null)] + [TestCase("plain", false, true, "C")] + public void ExperimentalDependenciesCoverSignaturesAndBodies(string shape, bool expressionBody, bool suppressBodyDependency, string? publicDiagnosticId) + { + var operation = InputFactory.Operation("UseDependencies"); + operation.Update(experimental: new InputExperimentalDetails(publicDiagnosticId, suppressBodyDependency ? ["A", "B"] : ["A"])); + var serviceMethod = InputFactory.BasicServiceMethod("UseDependencies", operation); + var inputClient = InputFactory.Client("TestClient", methods: [serviceMethod]); + MockHelpers.LoadMockGenerator(clients: () => [inputClient]); + var client = ScmCodeModelGenerator.Instance.TypeFactory.CreateClient(inputClient)!; + + var tree = CSharpSyntaxTree.ParseText(Helpers.GetExpectedFromFile()); + var references = AppDomain.CurrentDomain.GetAssemblies() + .Where(assembly => !assembly.IsDynamic && !string.IsNullOrEmpty(assembly.Location)) + .Select(assembly => MetadataReference.CreateFromFile(assembly.Location)); + var compilation = CSharpCompilation.Create( + "ExperimentalDependencies", + [tree], + references, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); + var dependency = compilation.GetTypeByMetadataName("Sample.SignatureDependency")!; + ITypeSymbol signatureSymbol = shape switch + { + "plain" => dependency, + "generic" => compilation.GetTypeByMetadataName("System.Collections.Generic.List`1")!.Construct(dependency), + "array" => compilation.CreateArrayTypeSymbol(dependency), + "nested" => compilation.GetTypeByMetadataName("System.Collections.Generic.List`1")!.Construct(compilation.CreateArrayTypeSymbol(dependency)), + _ => throw new ArgumentOutOfRangeException(nameof(shape)) + }; + var signatureType = signatureSymbol.GetCSharpType(); + var bodyType = compilation.GetTypeByMetadataName("Sample.BodyDependency")!.GetCSharpType(); + var parameter = new ParameterProvider("value", $"The value.", signatureType); + var attribute = ExperimentalApiHelpers.BuildAttribute(operation); + var signature = new MethodSignature( + "UseDependencies", null, MethodSignatureModifiers.Public, signatureType, null, [parameter], + Attributes: attribute is null ? [] : [attribute]); + var existingSuppression = new SuppressionStatement(null, Snippet.Literal("CS0168"), "Existing suppression."); + var method = expressionBody + ? new MethodProvider(signature, (ValueExpression)parameter, client, suppressions: [existingSuppression]) + : new MethodProvider(signature, new MethodBodyStatements( + [new ExpressionStatement(Snippet.New.Instance(bodyType)), Snippet.Return(parameter)]), client, suppressions: [existingSuppression]); + ExperimentalApiHelpers.AddDependencySuppressions(method, operation); + Assert.Contains(existingSuppression, method.Suppressions.ToArray()); + + using var writer = new CodeWriter(); + writer.WriteMethod(method); + var root = tree.GetRoot(); + var clientDeclaration = root.DescendantNodes().OfType().Single(c => c.Identifier.ValueText == "TestClient"); + var generatedMethod = SyntaxFactory.ParseMemberDeclaration(writer.ToString(false))!; + var updatedRoot = root.ReplaceNode(clientDeclaration, clientDeclaration.AddMembers(generatedMethod)); + var updatedTree = tree.WithRootAndOptions(updatedRoot, tree.Options); + compilation = compilation.ReplaceSyntaxTree(tree, updatedTree); + + var emittedMethod = updatedTree.GetRoot().DescendantNodes().OfType() + .Single(m => m.Identifier.ValueText == "UseDependencies"); + var diagnostics = compilation.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error).ToArray(); + var methodDiagnostics = diagnostics.Where(d => emittedMethod.Span.Contains(d.Location.SourceSpan)).ToArray(); + CollectionAssert.AreEqual( + suppressBodyDependency || expressionBody ? Array.Empty() : ["B"], + methodDiagnostics.Select(d => d.Id), + string.Join(Environment.NewLine, methodDiagnostics.Select(d => d.ToString()))); + var outsideDiagnostics = diagnostics.Where(d => !emittedMethod.Span.Contains(d.Location.SourceSpan)).ToArray(); + CollectionAssert.AreEquivalent( + publicDiagnosticId is null ? new[] { "A", "B" } : ["A", "B", "C"], + outsideDiagnostics.Select(d => d.Id).Distinct()); + } + + [TestCase(null)] + [TestCase("GENERATED001")] + public async Task ExperimentalCustomizedPartialMethodsKeepExistingAttributes(string? diagnosticId) + { + var operation = InputFactory.Operation("Bar"); + operation.Update(experimental: new InputExperimentalDetails(diagnosticId, [])); + var serviceMethod = InputFactory.BasicServiceMethod("Bar", operation); + var inputClient = InputFactory.Client("TestClient", methods: [serviceMethod]); + MockHelpers.LoadMockGenerator(); + var customCompilation = await Helpers.GetCompilationFromDirectoryAsync(); + await MockHelpers.LoadMockGeneratorAsync(clients: () => [inputClient], compilation: () => Task.FromResult(customCompilation)); + var client = ScmCodeModelGenerator.Instance.TypeFactory.CreateClient(inputClient)!; + var methods = new ScmMethodProviderCollection(serviceMethod, client); + var implementations = new List(); + + Assert.AreEqual(4, methods.Count); + foreach (var method in methods) + { + Assert.IsTrue(method.IsPartialMethod); + using var writer = new CodeWriter(); + writer.WriteMethod(method); + var declaration = (MethodDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration(writer.ToString(false))!; + implementations.Add(declaration + .WithModifiers(SyntaxFactory.TokenList(declaration.Modifiers.Where(m => !m.IsKind(SyntaxKind.AsyncKeyword)))) + .WithBody(SyntaxFactory.Block(SyntaxFactory.ThrowStatement(SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression))))); + } + + var customTree = customCompilation.SyntaxTrees.Single(t => t.GetRoot().DescendantNodes().OfType() + .Any(c => c.Identifier.ValueText == "TestClient")); + var root = customTree.GetRoot(); + var customClass = root.DescendantNodes().OfType().Single(c => c.Identifier.ValueText == "TestClient"); + var implementationRoot = root.ReplaceNode(customClass, customClass.WithMembers(SyntaxFactory.List(implementations))); + var compilation = customCompilation.RemoveAllSyntaxTrees().AddSyntaxTrees(customTree, CSharpSyntaxTree.Create((CSharpSyntaxNode)implementationRoot)); + var errors = compilation.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.IsEmpty(errors.Select(d => d.ToString()), "Customized attributes must occur only on the defining partial declaration."); + var symbol = compilation.GetTypeByMetadataName("Sample.TestClient")!; + foreach (var method in symbol.GetMembers().OfType().Where(m => m.Name is "Bar" or "BarAsync")) + { + Assert.AreEqual("CUSTOM001", method.GetAttributes().Single().ConstructorArguments[0].Value); + } + } + + [TestCase("plain", true)] + [TestCase("array", true)] + [TestCase("nested", true)] + [TestCase("plain", false)] + public async Task ExperimentalProductionMethodsCompile(string shape, bool suppressType) + { + var choice = InputFactory.StringEnum("Choice", [("One", "one")], isExtensible: true); + var payload = InputFactory.Model("Payload", usage: InputModelTypeUsage.Output | InputModelTypeUsage.Json); + InputType type = shape switch + { + "plain" => payload, + "array" => InputFactory.Array(payload), + "nested" => InputFactory.Array(InputFactory.Array(payload)), + _ => throw new ArgumentOutOfRangeException(nameof(shape)) + }; + var query = InputFactory.QueryParameter("value", choice, isRequired: true); + var operation = InputFactory.Operation("Read", parameters: [query], responses: [InputFactory.OperationResponse(bodytype: type)]); + operation.Update(experimental: new InputExperimentalDetails(null, suppressType ? ["A", "B"] : ["B"])); + var serviceMethod = InputFactory.BasicServiceMethod("Read", operation, parameters: + [InputFactory.MethodParameter("value", choice, isRequired: true, location: InputRequestLocation.Query)]); + var inputClient = InputFactory.Client("TestClient", methods: [serviceMethod]); + MockHelpers.LoadMockGenerator(); + var customCompilation = await Helpers.GetCompilationFromDirectoryAsync(); + await MockHelpers.LoadMockGeneratorAsync( + inputEnums: () => [choice], inputModels: () => [payload], clients: () => [inputClient], + compilation: () => Task.FromResult(customCompilation)); + var generator = ScmCodeModelGenerator.Instance; + var client = generator.TypeFactory.CreateClient(inputClient)!; + Assert.AreEqual(4, client.Methods.OfType().Count()); + foreach (var method in client.Methods.OfType().Append((ScmMethodProvider)client.RestClient.GetCreateRequestMethod(operation))) + { + CollectionAssert.AreEqual( + (suppressType ? new[] { "A", "B" } : ["B"]).Select(id => Snippet.Literal(id).ToDisplayString()), + method.Suppressions.Select(s => s.Code.ToDisplayString())); + } + + var customTree = customCompilation.SyntaxTrees.Single(t => t.GetRoot().DescendantNodes().OfType() + .Any(s => s.Identifier.ValueText == "Choice")); + // Isolate the client and serialization paths; this GET does not use request-content or model-factory APIs. + var providers = generator.OutputLibrary.TypeProviders + .Where(p => p is not Utf8JsonBinaryContentDefinition and not BinaryContentHelperDefinition and not ModelFactoryProvider).ToArray(); + var generatedTrees = providers.Concat(providers.SelectMany(p => p.SerializationProviders)) + .Select(p => new TypeProviderWriter(p).Write()) + .Select(file => CSharpSyntaxTree.ParseText(file.Content, path: file.Name)); + var compilation = customCompilation.RemoveAllSyntaxTrees() + .AddSyntaxTrees(customTree) + .AddSyntaxTrees(generatedTrees); + var errors = compilation.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error).ToArray(); + if (suppressType) + { + Assert.IsEmpty(errors.Select(d => d.ToString())); + } + else + { + Assert.IsTrue(errors.Length > 0); + Assert.IsTrue(errors.All(d => d.Id == "A"), string.Join(Environment.NewLine, errors.Select(d => d.ToString()))); + } + } + [Test] public void JsonLinesRequestGeneratesAsyncStreamingConvenienceMethod() { diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmModelProvider/ScmModelProviderTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmModelProvider/ScmModelProviderTests.cs index d5b58f5a7ca..dfe9960dbaa 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmModelProvider/ScmModelProviderTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmModelProvider/ScmModelProviderTests.cs @@ -18,6 +18,25 @@ namespace Microsoft.TypeSpec.Generator.ClientModel.Tests.Providers.ScmModelProvi { public class ScmModelProviderTests { + [Test] + public void ExperimentalModelAttributeIsNotRepeatedOnSerializationPartials() + { + var property = InputFactory.Experimental(InputFactory.Property("value", InputPrimitiveType.String), "PROPERTY001"); + var inputModel = InputFactory.Experimental(InputFactory.Model("Payload", properties: [property]), "MODEL001", "DEP001"); + MockHelpers.LoadMockGenerator(inputModels: () => [inputModel]); + var model = ScmCodeModelGenerator.Instance.TypeFactory.CreateModel(inputModel)!; + + Assert.AreEqual(1, model.Attributes.Count(a => a.Type.Equals(typeof(ExperimentalAttribute)))); + Assert.IsNotEmpty(model.SerializationProviders); + foreach (var serialization in model.SerializationProviders) + { + Assert.IsFalse(serialization.Attributes.Any(a => a.Type.Equals(typeof(ExperimentalAttribute)))); + CollectionAssert.IsSubsetOf( + new[] { "MODEL001", "DEP001", "PROPERTY001" }.Select(id => Snippet.Literal(id).ToDisplayString()), + serialization.DisabledFileWarnings.Select(s => s.Code.ToDisplayString())); + } + } + private sealed class DerivedScmModelProvider : ScmModel { public DerivedScmModelProvider(InputModelType inputModel) : base(inputModel) diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/TestData/ScmMethodProviderCollectionTests/ExperimentalCustomizedPartialMethodsKeepExistingAttributes/TestClient.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/TestData/ScmMethodProviderCollectionTests/ExperimentalCustomizedPartialMethodsKeepExistingAttributes/TestClient.cs new file mode 100644 index 00000000000..01b817b6f71 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/TestData/ScmMethodProviderCollectionTests/ExperimentalCustomizedPartialMethodsKeepExistingAttributes/TestClient.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Diagnostics.CodeAnalysis; +using System.Threading; +using System.Threading.Tasks; + +namespace Sample +{ + public partial class TestClient + { + [Experimental("CUSTOM001")] + public partial ClientResult Bar(RequestOptions options); + [Experimental("CUSTOM001")] + public partial Task BarAsync(RequestOptions options); + [Experimental("CUSTOM001")] + public partial ClientResult Bar(CancellationToken cancellationToken); + [Experimental("CUSTOM001")] + public partial Task BarAsync(CancellationToken cancellationToken); + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/TestData/ScmMethodProviderCollectionTests/ExperimentalDependenciesCoverSignaturesAndBodies.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/TestData/ScmMethodProviderCollectionTests/ExperimentalDependenciesCoverSignaturesAndBodies.cs new file mode 100644 index 00000000000..11c482ea116 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/TestData/ScmMethodProviderCollectionTests/ExperimentalDependenciesCoverSignaturesAndBodies.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Diagnostics.CodeAnalysis; + +namespace Sample +{ + [Experimental("A")] + public class SignatureDependency + { + } + + [Experimental("B")] + public class BodyDependency + { + } + + public class TestClient + { + } + + public class Consumer + { +#pragma warning disable A, B + public void Call(TestClient client) + { + client.UseDependencies(null); + } +#pragma warning restore A, B + + public SignatureDependency Unsuppressed(SignatureDependency value) + { + new BodyDependency(); + return value; + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/TestData/ScmMethodProviderCollectionTests/ExperimentalOperationSupportsPartialMethods/TestClient.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/TestData/ScmMethodProviderCollectionTests/ExperimentalOperationSupportsPartialMethods/TestClient.cs new file mode 100644 index 00000000000..6a22a011362 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/TestData/ScmMethodProviderCollectionTests/ExperimentalOperationSupportsPartialMethods/TestClient.cs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Threading; +using System.Threading.Tasks; + +namespace Sample +{ + public partial class TestClient + { + public partial ClientResult Bar(RequestOptions options); + public partial Task BarAsync(RequestOptions options); + public partial ClientResult Bar(CancellationToken cancellationToken); + public partial Task BarAsync(CancellationToken cancellationToken); + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/TestData/ScmMethodProviderCollectionTests/ExperimentalProductionMethodsCompile/Choice.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/TestData/ScmMethodProviderCollectionTests/ExperimentalProductionMethodsCompile/Choice.cs new file mode 100644 index 00000000000..55f06778c60 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/TestData/ScmMethodProviderCollectionTests/ExperimentalProductionMethodsCompile/Choice.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Diagnostics.CodeAnalysis; + +namespace Sample.Models +{ + public readonly partial struct Choice + { + [Experimental("B")] + public override string ToString() => _value; + } + + [Experimental("A")] + public partial class Payload + { + } +} + +namespace Sample +{ + public partial class SampleContext + { + public static SampleContext Default { get; } = new SampleContext(); + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputClient.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputClient.cs index 3ce5d3502c1..5b868eadb25 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputClient.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputClient.cs @@ -51,6 +51,7 @@ public InputClient() : this(string.Empty, string.Empty, string.Empty, string.Emp public InputClient? Parent { get; internal set; } public IReadOnlyList Children { get; internal set; } public IReadOnlyList Decorators { get; internal set; } = new List(); + public InputExperimentalDetails? Experimental { get; internal set; } public IReadOnlyList ApiVersions { get; internal set; } public string Key diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputExperimentalDetails.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputExperimentalDetails.cs new file mode 100644 index 00000000000..ca85c97ad11 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputExperimentalDetails.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Microsoft.TypeSpec.Generator.Input +{ + public sealed class InputExperimentalDetails + { + [JsonConstructor] + public InputExperimentalDetails(string? diagnosticId = null, IReadOnlyList? dependsOn = null) + { + DiagnosticId = diagnosticId; + DependsOn = dependsOn ?? []; + } + + [JsonPropertyName("diagnosticId")] + public string? DiagnosticId { get; } + + [JsonPropertyName("dependsOn")] + public IReadOnlyList DependsOn { get; } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputOperation.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputOperation.cs index 20e9f92bfe5..2bf8d28a7d9 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputOperation.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputOperation.cs @@ -102,6 +102,7 @@ public InputOperation() : this( public string CrossLanguageDefinitionId { get; internal set; } public IReadOnlyList Decorators { get; internal set; } = new List(); public IReadOnlyList Examples { get; internal set; } = new List(); + public InputExperimentalDetails? Experimental { get; internal set; } private bool? _isMultipartFormData; public bool IsMultipartFormData => _isMultipartFormData ??= RequestMediaTypes is not null && RequestMediaTypes.Count == 1 && RequestMediaTypes[0] == "multipart/form-data"; @@ -124,7 +125,8 @@ public void Update( bool? generateProtocolMethod = null, bool? generateConvenienceMethod = null, string? crossLanguageDefinitionId = null, - string? ns = null) + string? ns = null, + InputExperimentalDetails? experimental = null) { if (name != null) { @@ -198,6 +200,10 @@ public void Update( { Namespace = ns; } + if (experimental != null) + { + Experimental = experimental; + } } } } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputProperty.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputProperty.cs index 6a402bc5485..753c12d85ca 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputProperty.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputProperty.cs @@ -30,6 +30,7 @@ protected InputProperty(string name, string? summary, string? doc, InputType typ public string? Access { get; internal set; } public string SerializedName { get; internal set; } public IReadOnlyList Decorators { get; internal set; } = new List(); + public InputExperimentalDetails? Experimental { get; internal set; } public InputModelType? EnclosingType { get; internal set; } public bool IsApiVersion { get; internal set; } public InputConstant? DefaultValue { get; internal set; } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputType.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputType.cs index e118bd6809d..61432c48787 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputType.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/InputType.cs @@ -22,6 +22,7 @@ protected InputType(string name) public string Name { get; internal set; } public IReadOnlyList Decorators { get; internal set; } = new List(); public InputExternalTypeMetadata? External { get; internal set; } + public InputExperimentalDetails? Experimental { get; internal set; } /// /// Whether the name should be used exactly as-is, without casing transformations. /// diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputArrayTypeConverter.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputArrayTypeConverter.cs index c7b2eaf884f..6591e88575c 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputArrayTypeConverter.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputArrayTypeConverter.cs @@ -29,6 +29,7 @@ public static InputArrayType CreateListType(ref Utf8JsonReader reader, string? i InputType? valueType = null; IReadOnlyList? decorators = null; InputExternalTypeMetadata? external = null; + InputExperimentalDetails? experimental = null; while (reader.TokenType != JsonTokenType.EndObject) { var isKnownProperty = reader.TryReadReferenceId(ref id) @@ -36,7 +37,8 @@ public static InputArrayType CreateListType(ref Utf8JsonReader reader, string? i || reader.TryReadString("crossLanguageDefinitionId", ref crossLanguageDefinitionId) || reader.TryReadComplexType("valueType", options, ref valueType) || reader.TryReadComplexType("decorators", options, ref decorators) - || reader.TryReadComplexType("external", options, ref external); + || reader.TryReadComplexType("external", options, ref external) + || reader.TryReadComplexType("experimental", options, ref experimental); if (!isKnownProperty) { @@ -48,7 +50,8 @@ public static InputArrayType CreateListType(ref Utf8JsonReader reader, string? i var listType = new InputArrayType(name ?? "Array", crossLanguageDefinitionId ?? string.Empty, valueType) { Decorators = decorators ?? [], - External = external + External = external, + Experimental = experimental }; if (id != null) { diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputClientConverter.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputClientConverter.cs index eee7cc8ab6b..871acfaacf8 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputClientConverter.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputClientConverter.cs @@ -48,6 +48,7 @@ public override void Write(Utf8JsonWriter writer, InputClient value, JsonSeriali InputClient? parent = null; IReadOnlyList? children = null; IReadOnlyList? apiVersions = null; + InputExperimentalDetails? experimental = null; while (reader.TokenType != JsonTokenType.EndObject) { @@ -61,6 +62,7 @@ public override void Write(Utf8JsonWriter writer, InputClient value, JsonSeriali || reader.TryReadComplexType("parameters", options, ref parameters) || reader.TryReadInt32("initializedBy", ref initializedByValue) || reader.TryReadComplexType("decorators", options, ref decorators) + || reader.TryReadComplexType("experimental", options, ref experimental) || reader.TryReadString("crossLanguageDefinitionId", ref crossLanguageDefinitionId) || reader.TryReadComplexType("parent", options, ref parent) || reader.TryReadComplexType("children", options, ref children) @@ -86,6 +88,7 @@ public override void Write(Utf8JsonWriter writer, InputClient value, JsonSeriali client.Parent = parent; client.Children = children ?? []; client.ApiVersions = apiVersions ?? []; + client.Experimental = experimental; return client; } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputDateTimeTypeConverter.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputDateTimeTypeConverter.cs index 60641e7b697..d6537d5b98d 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputDateTimeTypeConverter.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputDateTimeTypeConverter.cs @@ -30,6 +30,7 @@ public static InputDateTimeType CreateDateTimeType(ref Utf8JsonReader reader, st IReadOnlyList? decorators = null; InputDateTimeType? baseType = null; InputExternalTypeMetadata? external = null; + InputExperimentalDetails? experimental = null; while (reader.TokenType != JsonTokenType.EndObject) { @@ -40,7 +41,8 @@ public static InputDateTimeType CreateDateTimeType(ref Utf8JsonReader reader, st || reader.TryReadComplexType("wireType", options, ref wireType) || reader.TryReadComplexType("baseType", options, ref baseType) || reader.TryReadComplexType("decorators", options, ref decorators) - || reader.TryReadComplexType("external", options, ref external); + || reader.TryReadComplexType("external", options, ref external) + || reader.TryReadComplexType("experimental", options, ref experimental); if (!isKnownProperty) { @@ -53,7 +55,7 @@ public static InputDateTimeType CreateDateTimeType(ref Utf8JsonReader reader, st encode = encode ?? throw new JsonException("DateTime type must have encoding"); wireType = wireType ?? throw new JsonException("DateTime type must have wireType"); - var dateTimeType = new InputDateTimeType(new DateTimeKnownEncoding(encode), name, crossLanguageDefinitionId, wireType, baseType) { Decorators = decorators ?? [], External = external }; + var dateTimeType = new InputDateTimeType(new DateTimeKnownEncoding(encode), name, crossLanguageDefinitionId, wireType, baseType) { Decorators = decorators ?? [], External = external, Experimental = experimental }; if (id != null) { diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputDictionaryTypeConverter.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputDictionaryTypeConverter.cs index 429cb5f396f..0cb0dc35109 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputDictionaryTypeConverter.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputDictionaryTypeConverter.cs @@ -29,13 +29,15 @@ public static InputDictionaryType CreateDictionaryType(ref Utf8JsonReader reader InputType? valueType = null; IReadOnlyList? decorators = null; InputExternalTypeMetadata? external = null; + InputExperimentalDetails? experimental = null; while (reader.TokenType != JsonTokenType.EndObject) { var isKnownProperty = reader.TryReadReferenceId(ref id) || reader.TryReadComplexType("keyType", options, ref keyType) || reader.TryReadComplexType("valueType", options, ref valueType) || reader.TryReadComplexType("decorators", options, ref decorators) - || reader.TryReadComplexType("external", options, ref external); + || reader.TryReadComplexType("external", options, ref external) + || reader.TryReadComplexType("experimental", options, ref experimental); if (!isKnownProperty) { @@ -49,7 +51,8 @@ public static InputDictionaryType CreateDictionaryType(ref Utf8JsonReader reader var dictType = new InputDictionaryType("Dictionary", keyType, valueType) { Decorators = decorators ?? [], - External = external + External = external, + Experimental = experimental }; if (id != null) { diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputDurationTypeConverter.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputDurationTypeConverter.cs index ee61696e9d2..4c9baebaa6a 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputDurationTypeConverter.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputDurationTypeConverter.cs @@ -31,6 +31,7 @@ public static InputDurationType CreateDurationType(ref Utf8JsonReader reader, st IReadOnlyList? decorators = null; InputDurationType? baseType = null; InputExternalTypeMetadata? external = null; + InputExperimentalDetails? experimental = null; while (reader.TokenType != JsonTokenType.EndObject) { @@ -41,7 +42,8 @@ public static InputDurationType CreateDurationType(ref Utf8JsonReader reader, st || reader.TryReadComplexType("wireType", options, ref wireType) || reader.TryReadComplexType("baseType", options, ref baseType) || reader.TryReadComplexType("decorators", options, ref decorators) - || reader.TryReadComplexType("external", options, ref external); + || reader.TryReadComplexType("external", options, ref external) + || reader.TryReadComplexType("experimental", options, ref experimental); if (!isKnownProperty) { @@ -59,7 +61,7 @@ public static InputDurationType CreateDurationType(ref Utf8JsonReader reader, st } wireType = wireType ?? throw new JsonException("Duration type must have wireType"); - var dateTimeType = new InputDurationType(new DurationKnownEncoding(encode), name, crossLanguageDefinitionId, wireType, baseType) { Decorators = decorators ?? [], External = external }; + var dateTimeType = new InputDurationType(new DurationKnownEncoding(encode), name, crossLanguageDefinitionId, wireType, baseType) { Decorators = decorators ?? [], External = external, Experimental = experimental }; if (id != null) { diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputEnumTypeConverter.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputEnumTypeConverter.cs index 77795bddc92..7bb2c8d6502 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputEnumTypeConverter.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputEnumTypeConverter.cs @@ -64,6 +64,7 @@ public static InputEnumType CreateEnumType(ref Utf8JsonReader reader, string? id InputExternalTypeMetadata? external = null; bool isExactName = false; IReadOnlyList? apiVersions = null; + InputExperimentalDetails? experimental = null; while (reader.TokenType != JsonTokenType.EndObject) { var isKnownProperty = reader.TryReadString("name", ref name) @@ -80,6 +81,7 @@ public static InputEnumType CreateEnumType(ref Utf8JsonReader reader, string? id || reader.TryReadComplexType("values", options, ref values) || reader.TryReadComplexType("decorators", options, ref decorators) || reader.TryReadComplexType("external", options, ref external) + || reader.TryReadComplexType("experimental", options, ref experimental) || reader.TryReadBoolean("isExactName", ref isExactName); if (!isKnownProperty) @@ -107,6 +109,7 @@ public static InputEnumType CreateEnumType(ref Utf8JsonReader reader, string? id enumType.External = external; enumType.IsExactName = isExactName; enumType.ApiVersions = apiVersions ?? []; + enumType.Experimental = experimental; return enumType; } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputEnumTypeValueConverter.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputEnumTypeValueConverter.cs index d0e067588bb..6ecd7e61d28 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputEnumTypeValueConverter.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputEnumTypeValueConverter.cs @@ -32,6 +32,7 @@ internal static InputEnumTypeValue CreateEnumTypeValue(ref Utf8JsonReader reader string? doc = null; IReadOnlyList? decorators = null; bool isExactName = false; + InputExperimentalDetails? experimental = null; while (reader.TokenType != JsonTokenType.EndObject) { var isKnownProperty = reader.TryReadReferenceId(ref id) @@ -42,6 +43,7 @@ internal static InputEnumTypeValue CreateEnumTypeValue(ref Utf8JsonReader reader || reader.TryReadString("summary", ref summary) || reader.TryReadString("doc", ref doc) || reader.TryReadComplexType("decorators", options, ref decorators) + || reader.TryReadComplexType("experimental", options, ref experimental) || reader.TryReadBoolean("isExactName", ref isExactName); if (!isKnownProperty) @@ -79,6 +81,7 @@ InputPrimitiveTypeKind.Decimal or InputPrimitiveTypeKind.Decimal128 => new InputEnumTypeFloatValue(name, rawValue.Value.GetSingle(), valueType, summary, doc, enumType) { Decorators = decorators ?? [], IsExactName = isExactName }, _ => throw new JsonException($"Unsupported enum valueType kind '{valueType.Kind}' for enum '{enumType.Name}' value '{name}'.") }; + enumValue.Experimental = experimental; if (id != null) { resolver.AddReference(id, enumValue); diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputModelPropertyConverter.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputModelPropertyConverter.cs index 72198a8a754..72a9e8b704a 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputModelPropertyConverter.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputModelPropertyConverter.cs @@ -68,6 +68,7 @@ internal static InputModelProperty ReadInputModelProperty(ref Utf8JsonReader rea string? encodeString = null; bool isExactName = false; IReadOnlyList? apiVersions = null; + InputExperimentalDetails? experimental = null; while (reader.TokenType != JsonTokenType.EndObject) { @@ -84,6 +85,7 @@ internal static InputModelProperty ReadInputModelProperty(ref Utf8JsonReader rea || reader.TryReadString("access", ref access) || reader.TryReadBoolean("discriminator", ref isDiscriminator) || reader.TryReadComplexType("decorators", options, ref decorators) + || reader.TryReadComplexType("experimental", options, ref experimental) || reader.TryReadString("serializedName", ref serializedName) || reader.TryReadBoolean("isApiVersion", ref isApiVersion) || reader.TryReadComplexType("defaultValue", options, ref defaultValue) @@ -114,6 +116,7 @@ internal static InputModelProperty ReadInputModelProperty(ref Utf8JsonReader rea property.Encode = Enum.TryParse(encodeString, ignoreCase: true, out var encode) ? encode : null; property.IsExactName = isExactName; property.ApiVersions = apiVersions ?? []; + property.Experimental = experimental; return property; } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputModelTypeConverter.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputModelTypeConverter.cs index 94077f29051..c916917122f 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputModelTypeConverter.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputModelTypeConverter.cs @@ -77,6 +77,7 @@ internal static InputModelType CreateModelType(ref Utf8JsonReader reader, string bool isExactName = false; bool isFileType = false; IReadOnlyList? apiVersions = null; + InputExperimentalDetails? experimental = null; // read all possible properties and throw away the unknown properties while (reader.TokenType != JsonTokenType.EndObject) @@ -99,6 +100,7 @@ internal static InputModelType CreateModelType(ref Utf8JsonReader reader, string || reader.TryReadComplexType("decorators", options, ref decorators) || reader.TryReadComplexType("serializationOptions", options, ref serializationOptions) || reader.TryReadComplexType("external", options, ref external) + || reader.TryReadComplexType("experimental", options, ref experimental) || reader.TryReadBoolean("isExactName", ref isExactName) || reader.TryReadBoolean("isFileType", ref isFileType) || reader.TryReadBoolean(nameof(InputModelType.ModelAsStruct), ref modelAsStruct); // TODO -- change this to fetch from the decorator list instead when the decorator is ready @@ -153,6 +155,7 @@ internal static InputModelType CreateModelType(ref Utf8JsonReader reader, string } model.External = external; model.IsFileType = isFileType; + model.Experimental = experimental; // if this model has a base, it means this model is a derived model of the base model, add it into the list. if (baseModel != null) diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputOperationConverter.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputOperationConverter.cs index 4225b8747c7..646a1f5cc61 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputOperationConverter.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputOperationConverter.cs @@ -57,6 +57,7 @@ public override void Write(Utf8JsonWriter writer, InputOperation value, JsonSeri IReadOnlyList? decorators = null; IReadOnlyList? examples = null; bool isExactName = false; + InputExperimentalDetails? experimental = null; while (reader.TokenType != JsonTokenType.EndObject) { @@ -80,7 +81,8 @@ public override void Write(Utf8JsonWriter writer, InputOperation value, JsonSeri || reader.TryReadString("crossLanguageDefinitionId", ref crossLanguageDefinitionId) || reader.TryReadComplexType("decorators", options, ref decorators) || reader.TryReadComplexType("examples", options, ref examples) - || reader.TryReadString("namespace", ref ns); + || reader.TryReadString("namespace", ref ns) + || reader.TryReadComplexType("experimental", options, ref experimental); if (!isKnownProperty) { @@ -110,6 +112,7 @@ public override void Write(Utf8JsonWriter writer, InputOperation value, JsonSeri operation.Decorators = decorators ?? []; operation.Examples = examples ?? []; operation.Namespace = ns; + operation.Experimental = experimental; return operation; } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputPrimitiveTypeConverter.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputPrimitiveTypeConverter.cs index 2388d03a364..295797a8a0a 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputPrimitiveTypeConverter.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputPrimitiveTypeConverter.cs @@ -30,6 +30,7 @@ public static InputPrimitiveType CreatePrimitiveType(ref Utf8JsonReader reader, InputPrimitiveType? baseType = null; IReadOnlyList? decorators = null; InputExternalTypeMetadata? external = null; + InputExperimentalDetails? experimental = null; bool isFileType = false; while (reader.TokenType != JsonTokenType.EndObject) { @@ -41,6 +42,7 @@ public static InputPrimitiveType CreatePrimitiveType(ref Utf8JsonReader reader, || reader.TryReadComplexType("baseType", options, ref baseType) || reader.TryReadComplexType("decorators", options, ref decorators) || reader.TryReadComplexType("external", options, ref external) + || reader.TryReadComplexType("experimental", options, ref experimental) || reader.TryReadBoolean("isFileType", ref isFileType); if (!isKnownProperty) @@ -62,6 +64,7 @@ public static InputPrimitiveType CreatePrimitiveType(ref Utf8JsonReader reader, { Decorators = decorators ?? [], External = external, + Experimental = experimental, IsFileType = isFileType }; if (id != null) diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputUnionTypeConverter.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputUnionTypeConverter.cs index 55e95f9f06f..0677f7fb83a 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputUnionTypeConverter.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/InputUnionTypeConverter.cs @@ -38,6 +38,7 @@ public static InputUnionType CreateInputUnionType(ref Utf8JsonReader reader, str IReadOnlyList? variantTypes = null; IReadOnlyList? decorators = null; InputExternalTypeMetadata? external = null; + InputExperimentalDetails? experimental = null; bool isExactName = false; while (reader.TokenType != JsonTokenType.EndObject) { @@ -45,6 +46,7 @@ public static InputUnionType CreateInputUnionType(ref Utf8JsonReader reader, str || reader.TryReadComplexType("variantTypes", options, ref variantTypes) || reader.TryReadComplexType("decorators", options, ref decorators) || reader.TryReadComplexType("external", options, ref external) + || reader.TryReadComplexType("experimental", options, ref experimental) || reader.TryReadBoolean("isExactName", ref isExactName); if (!isKnownProperty) @@ -61,6 +63,7 @@ public static InputUnionType CreateInputUnionType(ref Utf8JsonReader reader, str union.VariantTypes = variantTypes; union.Decorators = decorators ?? []; union.External = external; + union.Experimental = experimental; union.IsExactName = isExactName; return union; } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/TypeSpecInputNullableTypeConverter.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/TypeSpecInputNullableTypeConverter.cs index 55c6e6d2d1a..f81a0beb230 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/TypeSpecInputNullableTypeConverter.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/src/InputTypes/Serialization/TypeSpecInputNullableTypeConverter.cs @@ -27,13 +27,15 @@ public static InputNullableType CreateNullableType(ref Utf8JsonReader reader, st InputType? valueType = null; IReadOnlyList? decorators = null; InputExternalTypeMetadata? external = null; + InputExperimentalDetails? experimental = null; while (reader.TokenType != JsonTokenType.EndObject) { var isKnownProperty = reader.TryReadReferenceId(ref id) || reader.TryReadString("name", ref name) || reader.TryReadComplexType("type", options, ref valueType) || reader.TryReadComplexType("decorators", options, ref decorators) - || reader.TryReadComplexType("external", options, ref external); + || reader.TryReadComplexType("external", options, ref external) + || reader.TryReadComplexType("experimental", options, ref experimental); if (!isKnownProperty) { @@ -46,7 +48,8 @@ public static InputNullableType CreateNullableType(ref Utf8JsonReader reader, st var nullableType = new InputNullableType(valueType) { Decorators = decorators ?? [], - External = external + External = external, + Experimental = experimental }; if (id != null) { diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/test/TypeSpecInputConverterTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/test/TypeSpecInputConverterTests.cs index 1ba2deefa71..ae4ee05a3dd 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/test/TypeSpecInputConverterTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.Input/test/TypeSpecInputConverterTests.cs @@ -10,6 +10,134 @@ namespace Microsoft.TypeSpec.Generator.Input.Tests { public class TypeSpecInputConverterTests { + [TestCase("model", "\"properties\": []")] + [TestCase("enum", "\"values\": [], \"valueType\": {\"kind\":\"string\"}")] + [TestCase("string", "\"crossLanguageDefinitionId\": \"External.Value\"")] + [TestCase("union", "\"variantTypes\": [{\"kind\":\"string\"}, {\"kind\":\"int32\"}]")] + [TestCase("array", "\"valueType\": {\"kind\":\"string\"}")] + [TestCase("dict", "\"keyType\": {\"kind\":\"string\"}, \"valueType\": {\"kind\":\"string\"}")] + [TestCase("nullable", "\"type\": {\"kind\":\"string\"}")] + [TestCase("utcDateTime", "\"crossLanguageDefinitionId\":\"External.Value\", \"encode\":\"rfc3339\", \"wireType\":{\"kind\":\"string\"}")] + [TestCase("duration", "\"crossLanguageDefinitionId\":\"External.Value\", \"encode\":\"ISO8601\", \"wireType\":{\"kind\":\"string\"}")] + public void LoadsExperimentalExternalTypes(string kind, string typeProperties) + { + var content = $$""" + { + "name": "Test", + "models": [{ + "$id": "wrapper", "name": "Wrapper", + "properties": [{ + "$id": "property", "name": "value", + "type": { + "$id": "external", "kind": "{{kind}}", "name": "External", + {{typeProperties}}, + "external": {"identity":"External.Value"}, + "experimental": {"diagnosticId":"EXTERNAL001","dependsOn":["DEP001"]} + } + }] + }] + } + """; + var type = TypeSpecSerialization.Deserialize(content)!.Models.Single().Properties.Single().Type; + Assert.AreEqual("External.Value", type.External?.Identity); + Assert.AreEqual("EXTERNAL001", type.Experimental?.DiagnosticId); + CollectionAssert.AreEqual(new[] { "DEP001" }, type.Experimental!.DependsOn); + Assert.IsNull(InputPrimitiveType.String.Experimental); + } + + [TestCase(true)] + [TestCase(false)] + public void LoadsExperimentalTypesAndMembers(bool annotated) + { + string Metadata(string id) => annotated + ? $"\"experimental\": {{\"diagnosticId\":\"{id}\",\"dependsOn\":[\"DEP001\"]}}," + : ""; + var content = $$""" + { + "name": "Test", + "models": [{ + "$id": "model", "name": "Payload", {{Metadata("MODEL001")}} + "properties": [{ + "$id": "property", "name": "value", {{Metadata("PROPERTY001")}} + "type": {"kind":"string"} + }] + }], + "enums": [{ + "$id": "enum", "name": "Choice", {{Metadata("ENUM001")}} + "valueType": {"kind":"string"}, + "values": [{ + "$id": "value", "name": "One", "value": "one", {{Metadata("VALUE001")}} + "valueType": {"kind":"string"}, "enumType": {"$ref":"enum"} + }] + }], + "clients": [{ + "$id": "client", "name": "TestClient", {{Metadata("CLIENT001")}} + "methods": [] + }] + } + """; + var input = TypeSpecSerialization.Deserialize(content)!; + var details = new[] + { + input.Models[0].Experimental, + input.Models[0].Properties[0].Experimental, + input.Enums[0].Experimental, + input.Enums[0].Values[0].Experimental, + input.Clients[0].Experimental + }; + if (annotated) + { + CollectionAssert.AreEqual( + new[] { "MODEL001", "PROPERTY001", "ENUM001", "VALUE001", "CLIENT001" }, + details.Select(d => d?.DiagnosticId)); + Assert.IsTrue(details.All(d => d!.DependsOn.SequenceEqual(["DEP001"]))); + } + else + { + Assert.IsTrue(details.All(d => d is null)); + } + } + + [TestCase("""{"diagnosticId":"C","dependsOn":["A","B"]}""", "C", new[] { "A", "B" })] + [TestCase("""{"diagnosticId":"C"}""", "C", new string[0])] + [TestCase("""{"dependsOn":["A"]}""", null, new[] { "A" })] + [TestCase("""{}""", null, new string[0])] + [TestCase("""null""", null, null)] + [TestCase(null, null, null)] + public void LoadsExperimentalOperationDetails(string? experimental, string? diagnosticId, string[]? dependencies) + { + var content = $$""" + { + "$id": "operation", + "name": "bar", + "httpMethod": "GET", + "uri": "", + "path": "", + {{(experimental is null ? "" : $@"""experimental"": {experimental},")}} + "crossLanguageDefinitionId": "Test.bar" + } + """; + var referenceHandler = new TypeSpecReferenceHandler(); + var options = new JsonSerializerOptions + { + ReferenceHandler = referenceHandler, + Converters = { new InputOperationConverter(referenceHandler) } + }; + + var operation = JsonSerializer.Deserialize(content, options)!; + + if (dependencies is null) + { + Assert.IsNull(operation.Experimental); + } + else + { + Assert.IsNotNull(operation.Experimental); + Assert.AreEqual(diagnosticId, operation.Experimental!.DiagnosticId); + CollectionAssert.AreEqual(dependencies, operation.Experimental.DependsOn); + } + } + [Test] public void LoadsEmitterFixture() { diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Primitives/EnumTypeMember.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Primitives/EnumTypeMember.cs index ccdea34eb9b..35b94bb8f9d 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Primitives/EnumTypeMember.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Primitives/EnumTypeMember.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using Microsoft.TypeSpec.Generator.Providers; +using Microsoft.TypeSpec.Generator.Input; namespace Microsoft.TypeSpec.Generator.Primitives { @@ -19,5 +20,6 @@ public EnumTypeMember(string name, FieldProvider field, object value) public FieldProvider Field { get; } public object Value { get; } + internal InputExperimentalDetails? Experimental { get; init; } } } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ApiVersionEnumProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ApiVersionEnumProvider.cs index 6bceafce8a5..193ef391f29 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ApiVersionEnumProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ApiVersionEnumProvider.cs @@ -99,9 +99,10 @@ protected override IReadOnlyList BuildEnumValues() name, this, DocHelpers.GetFormattableDescription(inputValue.Summary, inputValue.Doc) ?? $"{name}", - initializationValue); + initializationValue, + attributes: ExperimentalApiHelpers.BuildAttributes(inputValue.Experimental)); - values.Add(new EnumTypeMember(name, field, inputValue.Value)); + values.Add(new EnumTypeMember(name, field, inputValue.Value) { Experimental = inputValue.Experimental }); } } @@ -116,17 +117,17 @@ private List BuildCustomEnumMembers(IReadOnlyList { var member = customMembers[i]; var modifiers = FieldModifiers.Public | FieldModifiers.Static; + allowedValues.TryGetValue(member.OriginalName ?? member.Name, out var enumValue); var field = new FieldProvider( modifiers, EnumUnderlyingType, member.Name, this, $"", - member.InitializationValue); - object? inputValue = allowedValues.TryGetValue(member.OriginalName ?? member.Name, out var enumValue) - ? enumValue.Value - : member.Name; - values.Add(new EnumTypeMember(member.Name, field, inputValue)); + member.InitializationValue, + attributes: ExperimentalApiHelpers.BuildAttributes(enumValue?.Experimental)); + object inputValue = enumValue?.Value ?? member.Name; + values.Add(new EnumTypeMember(member.Name, field, inputValue) { Experimental = enumValue?.Experimental }); } return values; @@ -180,8 +181,9 @@ private List BuildApiVersionEnumValuesForBackwardCompatibility(L member.Name, member.Field.EnclosingType, member.Field.Description, - Literal(i + 1)); - allMembers[i] = new EnumTypeMember(member.Name, updatedField, member.Value); + Literal(i + 1), + attributes: member.Field.Attributes); + allMembers[i] = new EnumTypeMember(member.Name, updatedField, member.Value) { Experimental = member.Experimental }; } return allMembers; diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ExtensibleEnumProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ExtensibleEnumProvider.cs index 7cdb0e11e9f..904def1ca0c 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ExtensibleEnumProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ExtensibleEnumProvider.cs @@ -74,7 +74,7 @@ protected override IReadOnlyList BuildEnumValues() DocHelpers.GetFormattableDescription(inputValue.Summary, inputValue.Doc), initializationValue); - values[i] = new EnumTypeMember(valueName, field, inputValue.Value); + values[i] = new EnumTypeMember(valueName, field, inputValue.Value) { Experimental = inputValue.Experimental }; } return values; @@ -101,7 +101,8 @@ protected internal override PropertyProvider[] BuildProperties() type: Type, name: name, body: new AutoPropertyBody(false, InitializationExpression: New.Instance(Type, field)), - this); + this, + attributes: ExperimentalApiHelpers.BuildAttributes(enumValue.Experimental)); } return properties; diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/FixedEnumProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/FixedEnumProvider.cs index 56ae107d419..c243be1fb4d 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/FixedEnumProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/FixedEnumProvider.cs @@ -112,9 +112,10 @@ protected override IReadOnlyList BuildEnumValues() name, this, DocHelpers.GetFormattableDescription(inputValue.Summary, inputValue.Doc) ?? $"{name}", - initializationValue); + initializationValue, + attributes: ExperimentalApiHelpers.BuildAttributes(inputValue.Experimental)); - values[i] = new EnumTypeMember(name, field, inputValue.Value); + values[i] = new EnumTypeMember(name, field, inputValue.Value) { Experimental = inputValue.Experimental }; } return values; } @@ -155,8 +156,9 @@ protected override IReadOnlyList BuildEnumValues() existingMember.Name, existingMember.Field.EnclosingType, existingMember.Field.Description, - initializationValue); - allMembers.Add(new EnumTypeMember(existingMember.Name, updatedField, memberValue)); + initializationValue, + attributes: existingMember.Field.Attributes); + allMembers.Add(new EnumTypeMember(existingMember.Name, updatedField, memberValue) { Experimental = existingMember.Experimental }); } else if (customMemberLastContractNames.Contains(field.Name)) { diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ModelFactoryProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ModelFactoryProvider.cs index cbc6ac9c06c..07c108e95ad 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ModelFactoryProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ModelFactoryProvider.cs @@ -36,6 +36,9 @@ protected internal ModelFactoryProvider(IEnumerable models) protected override string BuildRelativeFilePath() => Path.Combine("src", "Generated", $"{Name}.cs"); + protected internal override SuppressionStatement[] BuildDisabledFileWarnings() + => ExperimentalApiHelpers.GetSuppressions(_models); + protected override TypeSignatureModifiers BuildDeclarationModifiers() => TypeSignatureModifiers.Static | TypeSignatureModifiers.Partial | TypeSignatureModifiers.Class; @@ -74,7 +77,8 @@ protected internal override MethodProvider[] BuildMethods() MethodSignatureModifiers.Static | MethodSignatureModifiers.Public, modelProvider.Type, $"A new {modelProvider.Type:C} instance for mocking.", - GetParameters(modelProvider, fullConstructor)); + GetParameters(modelProvider, fullConstructor), + Attributes: ExperimentalApiHelpers.BuildAttributes(model.Experimental)); var parameters = new List(signature.Parameters.Count); foreach (var param in signature.Parameters) diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/NamedTypeSymbolProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/NamedTypeSymbolProvider.cs index 613c9e34108..88cc9a5ec79 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/NamedTypeSymbolProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/NamedTypeSymbolProvider.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Xml; @@ -345,6 +346,9 @@ protected internal override MethodProvider[] BuildMethods() GetNullableCSharpType(methodSymbol.ReturnType), GetSymbolXmlDoc(methodSymbol, "returns"), [.. methodSymbol.Parameters.Select(p => ConvertToParameterProvider(methodSymbol, p))], + Attributes: [.. methodSymbol.GetAttributes() + .Where(a => a.AttributeClass?.ToDisplayString() == typeof(ExperimentalAttribute).FullName) + .Select(a => new AttributeStatement(a))], GenericArguments: methodSymbol.TypeParameters.IsEmpty ? null : [.. methodSymbol.TypeParameters.Select(parameter => parameter.GetCSharpType())], diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/PropertyProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/PropertyProvider.cs index 758c7dbe09f..5ff15415af8 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/PropertyProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/PropertyProvider.cs @@ -143,7 +143,7 @@ private PropertyProvider(InputProperty inputProperty, CSharpType propertyType, T Body = new AutoPropertyBody(propHasSetter, setterModifier, GetPropertyInitializationValue(propertyType, inputProperty)); WireInfo = new PropertyWireInformation(inputProperty); - Attributes = []; + Attributes = ExperimentalApiHelpers.BuildAttributes(inputProperty.Experimental); InitializeParameter(DocHelpers.GetFormattableDescription(inputProperty.Summary, inputProperty.Doc) ?? FormattableStringHelpers.Empty); BuildDocs(); diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/TypeProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/TypeProvider.cs index 52e2fb28618..df3d6eb132f 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/TypeProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/TypeProvider.cs @@ -287,7 +287,11 @@ LastContractView is { } lastContractView && protected virtual CSharpType? BuildBaseType() => null; private IReadOnlyList? _disabledFileWarnings; - public IReadOnlyList DisabledFileWarnings => _disabledFileWarnings ??= BuildDisabledFileWarnings(); + public IReadOnlyList DisabledFileWarnings => _disabledFileWarnings ??= + ExperimentalApiHelpers.MergeSuppressions( + BuildDisabledFileWarnings(), + ExperimentalApiHelpers.GetSuppressions(_inputType ?? SerializationProviderOwner?._inputType), + NestedTypes.SelectMany(type => type.DisabledFileWarnings)); private protected virtual bool FilterCustomizedMembers => true; @@ -721,7 +725,13 @@ private IReadOnlyList AssignSerializationProviderOwners(IEnumerabl protected virtual CSharpType BuildEnumUnderlyingType() => throw new InvalidOperationException("Not an EnumProvider type"); - protected virtual IReadOnlyList BuildAttributes() => []; + protected virtual IReadOnlyList BuildAttributes() + { + var attribute = ExperimentalApiHelpers.BuildAttribute(_inputType?.Experimental); + return attribute is null || CustomCodeView?.Attributes.Any(a => a.Type.Equals(attribute.Type)) == true + ? [] + : [attribute]; + } private CSharpType? _enumUnderlyingType; diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/BackCompatHelper.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/BackCompatHelper.cs index 5123a920e7b..585d589e64a 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/BackCompatHelper.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/BackCompatHelper.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.TypeSpec.Generator.EmitterRpc; using Microsoft.TypeSpec.Generator.Expressions; @@ -487,6 +488,10 @@ public static void AddBackCompatOverloads(TypeProvider enclosingType, List MethodSignatureBase.SignatureComparer.Equals(method.Signature, currentMethod.Signature)) + : null; + var attribute = customMethod?.Signature.Attributes.FirstOrDefault(a => a.Type.Equals(typeof(ExperimentalAttribute))) + ?? currentMethod.Signature.Attributes.FirstOrDefault(a => a.Type.Equals(typeof(ExperimentalAttribute))); + + // Graduation and custom partial attributes follow the current API, not the last contract. + overload.Signature.Update(attributes: + [ + .. overload.Signature.Attributes.Where(a => !a.Type.Equals(typeof(ExperimentalAttribute))), + .. attribute is null ? Array.Empty() : [attribute] + ]); + overload.Update(suppressions: ExperimentalApiHelpers.MergeSuppressions(overload.Suppressions, currentMethod.Suppressions)); + } + // Returns true when both signatures have the same return type (matched by name); a null return type // matches only another null return type. Compares in both directions so that a return type whose // (possibly generic) parts are unresolved in the customization compilation still matches by name. diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/ExperimentalApiHelpers.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/ExperimentalApiHelpers.cs new file mode 100644 index 00000000000..32a6beda738 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/ExperimentalApiHelpers.cs @@ -0,0 +1,235 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text.RegularExpressions; +using Microsoft.TypeSpec.Generator.Input; +using Microsoft.TypeSpec.Generator.Providers; +using Microsoft.TypeSpec.Generator.Statements; +using static Microsoft.TypeSpec.Generator.Snippets.Snippet; + +namespace Microsoft.TypeSpec.Generator.Utilities +{ + public static class ExperimentalApiHelpers + { + public static AttributeStatement? BuildAttribute(InputOperation operation) + => BuildAttribute(operation.Experimental); + + public static AttributeStatement? BuildAttribute(InputExperimentalDetails? details) + { + if (details?.DiagnosticId is not { } diagnosticId) + { + return null; + } + ValidateDiagnosticId(diagnosticId); + return new AttributeStatement(typeof(ExperimentalAttribute), [Literal(diagnosticId)]); + } + + public static AttributeStatement[] BuildAttributes(InputExperimentalDetails? details) + => BuildAttribute(details) is { } attribute ? [attribute] : []; + + public static void AddDependencySuppressions(MethodProvider method, InputOperation operation) + { + if (operation.Experimental?.DependsOn is not { Count: > 0 } dependencies) + { + return; + } + + var fileSuppressions = method.EnclosingType.DisabledFileWarnings + .Select(s => s.Code.ToDisplayString()).ToHashSet(StringComparer.Ordinal); + method.Update(suppressions: MergeSuppressions( + method.Suppressions, + CreateSuppressions(dependencies).Where(s => !fileSuppressions.Contains(s.Code.ToDisplayString())))); + } + + public static SuppressionStatement[] GetSuppressions(InputType? type) + => GetSuppressions(type is null ? [] : new[] { type }); + + public static SuppressionStatement[] GetSuppressions(IEnumerable types) + { + var collector = new DiagnosticCollector(); + foreach (var type in types) + { + collector.AddDeclaration(type); + } + return CreateSuppressions(collector.Ids.Order(StringComparer.Ordinal)); + } + + public static SuppressionStatement[] GetSuppressions(InputClient client) + { + var collector = new DiagnosticCollector(); + collector.AddMetadata(client.Experimental); + collector.AddId(client.Parent?.Experimental?.DiagnosticId); + foreach (var child in client.Children) + { + collector.AddId(child.Experimental?.DiagnosticId); + foreach (var parameter in child.Parameters) + { + collector.AddProperty(parameter); + } + } + foreach (var parameter in client.Parameters) + { + collector.AddProperty(parameter); + } + foreach (var method in client.Methods) + { + foreach (var parameter in method.Parameters.Concat(method.Operation.Parameters)) + { + collector.AddProperty(parameter); + } + collector.AddReference(method.Response.Type); + foreach (var response in method.Operation.Responses) + { + collector.AddReference(response.BodyType); + } + } + return CreateSuppressions(collector.Ids.Order(StringComparer.Ordinal)); + } + + public static SuppressionStatement[] GetParameterSuppressions(IEnumerable parameters) + { + var collector = new DiagnosticCollector(); + foreach (var parameter in parameters) + { + collector.AddProperty(parameter); + } + return CreateSuppressions(collector.Ids.Order(StringComparer.Ordinal)); + } + + public static SuppressionStatement[] GetSuppressions(InputOperation operation, InputClient? client = null) + { + var collector = new DiagnosticCollector(); + collector.AddMetadata(client?.Experimental); + collector.AddMetadata(operation.Experimental); + foreach (var parameter in operation.Parameters) + { + collector.AddProperty(parameter); + } + foreach (var response in operation.Responses) + { + collector.AddReference(response.BodyType); + } + return CreateSuppressions(collector.Ids.Order(StringComparer.Ordinal)); + } + + public static SuppressionStatement[] MergeSuppressions(params IEnumerable[] suppressions) + => [.. suppressions.SelectMany(s => s).DistinctBy(s => s.Code.ToDisplayString())]; + + private static SuppressionStatement[] CreateSuppressions(IEnumerable diagnosticIds) + => [.. diagnosticIds.Distinct(StringComparer.Ordinal).Select(id => + { + ValidateDiagnosticId(id); + return new SuppressionStatement(null, Literal(id), "This generated code depends on experimental functionality."); + })]; + + private static void ValidateDiagnosticId(string diagnosticId) + { + if (!Regex.IsMatch(diagnosticId, @"\A(?:[A-Za-z_][A-Za-z0-9_]*|[0-9]+)\z", RegexOptions.CultureInvariant)) + { + throw new ArgumentException("Experimental diagnostic IDs must be single C# warning identifiers or decimal warning numbers.", nameof(diagnosticId)); + } + } + + private sealed class DiagnosticCollector + { + private readonly HashSet _declarations = []; + private readonly HashSet _references = []; + public HashSet Ids { get; } = new(StringComparer.Ordinal); + + public void AddId(string? id) + { + if (id is not null) + { + ValidateDiagnosticId(id); + Ids.Add(id); + } + } + + public void AddMetadata(InputExperimentalDetails? details) + { + AddId(details?.DiagnosticId); + foreach (var dependency in details?.DependsOn ?? []) + { + AddId(dependency); + } + } + + public void AddProperty(InputProperty property) + { + AddMetadata(property.Experimental); + AddReference(property.Type); + AddReference(property.DefaultValue?.Type); + } + + public void AddDeclaration(InputType type) + { + if (!_declarations.Add(type)) + { + return; + } + AddMetadata(type.Experimental); + if (type is InputModelType model) + { + foreach (var property in model.Properties) + { + AddProperty(property); + } + if (model.BaseModel is { } baseModel) + { + AddDeclaration(baseModel); + } + AddReference(model.AdditionalProperties); + foreach (var derived in model.DerivedModels) + { + AddReference(derived); + } + } + else if (type is InputEnumType enumType) + { + foreach (var value in enumType.Values) + { + AddMetadata(value.Experimental); + } + } + } + + public void AddReference(InputType? type) + { + if (type is null || !_references.Add(type)) + { + return; + } + AddId(type.Experimental?.DiagnosticId); + switch (type) + { + case InputArrayType array: + AddReference(array.ValueType); + break; + case InputStreamingType streaming: + AddReference(streaming.ValueType); + break; + case InputDictionaryType dictionary: + AddReference(dictionary.KeyType); + AddReference(dictionary.ValueType); + break; + case InputNullableType nullable: + AddReference(nullable.Type); + break; + case InputUnionType union: + foreach (var variant in union.VariantTypes) + { + AddReference(variant); + } + break; + case InputEnumTypeValue value: + AddReference(value.EnumType); + break; + } + } + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/TestData/TypeProviderTests/ExperimentalBackCompatOverloadsFollowCurrentMetadata/ExperimentalCompatibility.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/TestData/TypeProviderTests/ExperimentalBackCompatOverloadsFollowCurrentMetadata/ExperimentalCompatibility.cs new file mode 100644 index 00000000000..6d390bc98f8 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/TestData/TypeProviderTests/ExperimentalBackCompatOverloadsFollowCurrentMetadata/ExperimentalCompatibility.cs @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Diagnostics.CodeAnalysis; + +namespace Test +{ + public class ExperimentalCompatibility + { + [Experimental("PREVIOUS001")] + public void AddOptional(int value) { } + + [Experimental("PREVIOUS001")] + public void RemoveNullability(int? value) { } + + [Experimental("PREVIOUS001")] + public void RequireOptional(int? value = null) { } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/TypeProviderTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/TypeProviderTests.cs index 111188784fd..a50557bab5e 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/TypeProviderTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/TypeProviderTests.cs @@ -3,9 +3,13 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.TypeSpec.Generator.Input; using Microsoft.TypeSpec.Generator.Primitives; using Microsoft.TypeSpec.Generator.Providers; @@ -19,6 +23,152 @@ namespace Microsoft.TypeSpec.Generator.Tests.Providers { public class TypeProviderTests { + [TestCase("CURRENT001", false)] + [TestCase("CURRENT001", true)] + [TestCase(null, true)] + public async Task ExperimentalBackCompatOverloadsFollowCurrentMetadata(string? diagnosticId, bool previouslyExperimental) + { + await MockHelpers.LoadMockGeneratorAsync(lastContractCompilation: async () => + { + var compilation = await Helpers.GetCompilationFromDirectoryAsync(); + if (previouslyExperimental) + { + return compilation; + } + var tree = compilation.SyntaxTrees.Single(t => t.FilePath.EndsWith("ExperimentalCompatibility.cs", StringComparison.Ordinal)); + var root = tree.GetRoot(); + var updatedRoot = root.ReplaceNodes(root.DescendantNodes().OfType(), + (_, method) => method.WithAttributeLists(default)); + return compilation.ReplaceSyntaxTree(tree, tree.WithRootAndOptions(updatedRoot, tree.Options)); + }); + var owner = new TestTypeProvider(name: "ExperimentalCompatibility", ns: "Test"); + var attributes = ExperimentalApiHelpers.BuildAttributes(new InputExperimentalDetails(diagnosticId)); + var suppressions = new[] + { + new SuppressionStatement(null, Snippet.Literal("DEP001"), "Dependency one."), + new SuppressionStatement(null, Snippet.Literal("DEP002"), "Dependency two.") + }; + MethodProvider CreateMethod(string name, params ParameterProvider[] parameters) => new( + new MethodSignature(name, null, MethodSignatureModifiers.Public, null, null, parameters, Attributes: attributes), + Snippet.Throw(Snippet.Null), owner, suppressions: suppressions); + owner.Update(methods: + [ + CreateMethod("AddOptional", + new ParameterProvider("value", $"", typeof(int)), + new ParameterProvider("added", $"", typeof(bool), defaultValue: Snippet.Default, location: ParameterLocation.Query)), + CreateMethod("RemoveNullability", new ParameterProvider("value", $"", typeof(int))), + CreateMethod("RequireOptional", new ParameterProvider("value", $"", typeof(int?))) + ]); + + owner.ProcessTypeForBackCompatibility(); + var shims = owner.Methods.Where(m => m.Signature.Attributes.Any(a => a.Type.Equals(typeof(EditorBrowsableAttribute)))).ToArray(); + Assert.AreEqual(3, shims.Length); + foreach (var shim in shims) + { + var experiment = shim.Signature.Attributes.SingleOrDefault(a => a.Type.Equals(typeof(ExperimentalAttribute))); + Assert.AreEqual(diagnosticId is null ? null : Snippet.Literal(diagnosticId).ToDisplayString(), + experiment?.Arguments[0].ToDisplayString()); + CollectionAssert.AreEqual( + suppressions.Select(s => s.Code.ToDisplayString()), + shim.Suppressions.Select(s => s.Code.ToDisplayString())); + } + + var references = AppDomain.CurrentDomain.GetAssemblies() + .Where(a => !a.IsDynamic && !string.IsNullOrEmpty(a.Location)) + .Select(a => MetadataReference.CreateFromFile(a.Location)); + var compilation = CSharpCompilation.Create( + "ExperimentalCompatibility", + [CSharpSyntaxTree.ParseText(new TypeProviderWriter(owner).Write().Content), + CSharpSyntaxTree.ParseText(new TypeProviderWriter(new ArgumentDefinition()).Write().Content)], + references, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, generalDiagnosticOption: ReportDiagnostic.Error)); + Assert.IsEmpty(compilation.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error).Select(d => d.ToString())); + } + + [TestCase(false)] + [TestCase(true)] + public void ExperimentalModelsAndProperties(bool modelAsStruct) + { + MockHelpers.LoadMockGenerator(); + var property = InputFactory.Experimental(InputFactory.Property("value", InputPrimitiveType.String), "PROPERTY001", "PROPERTYDEP"); + var model = InputFactory.Experimental( + InputFactory.Model("Payload", modelAsStruct: modelAsStruct, properties: [property]), + "MODEL001", "MODELDEP"); + var provider = CodeModelGenerator.Instance.TypeFactory.CreateModel(model)!; + + Assert.AreEqual(Snippet.Literal("MODEL001").ToDisplayString(), + provider.Attributes.Single(a => a.Type.Equals(typeof(ExperimentalAttribute))).Arguments[0].ToDisplayString()); + Assert.AreEqual(Snippet.Literal("PROPERTY001").ToDisplayString(), + provider.Properties.Single(p => p.Name == "Value").Attributes.Single(a => a.Type.Equals(typeof(ExperimentalAttribute))).Arguments[0].ToDisplayString()); + CollectionAssert.AreEquivalent( + new[] { "MODEL001", "MODELDEP", "PROPERTY001", "PROPERTYDEP" }.Select(id => Snippet.Literal(id).ToDisplayString()), + provider.DisabledFileWarnings.Select(s => s.Code.ToDisplayString())); + } + + [TestCase(false)] + [TestCase(true)] + public void ExperimentalEnumsAndMembers(bool isExtensible) + { + MockHelpers.LoadMockGenerator(); + var input = InputFactory.Experimental( + InputFactory.StringEnum("Choice", [("One", "one"), ("Two", "two")], isExtensible: isExtensible), + "ENUM001", "ENUMDEP"); + InputFactory.Experimental(input.Values[0], "MEMBER001", "MEMBERDEP"); + var provider = CodeModelGenerator.Instance.TypeFactory.CreateEnum(input)!; + var attributes = isExtensible + ? provider.Properties.Single(p => p.Name == "One").Attributes + : provider.EnumValues.Single(v => v.Name == "One").Field.Attributes; + + Assert.AreEqual(Snippet.Literal("ENUM001").ToDisplayString(), + provider.Attributes.Single(a => a.Type.Equals(typeof(ExperimentalAttribute))).Arguments[0].ToDisplayString()); + Assert.AreEqual(Snippet.Literal("MEMBER001").ToDisplayString(), + attributes.Single(a => a.Type.Equals(typeof(ExperimentalAttribute))).Arguments[0].ToDisplayString()); + CollectionAssert.AreEquivalent( + new[] { "ENUM001", "ENUMDEP", "MEMBER001", "MEMBERDEP" }.Select(id => Snippet.Literal(id).ToDisplayString()), + provider.DisabledFileWarnings.Select(s => s.Code.ToDisplayString())); + var controlAttributes = isExtensible + ? provider.Properties.Single(p => p.Name == "Two").Attributes + : provider.EnumValues.Single(v => v.Name == "Two").Field.Attributes; + Assert.IsFalse(controlAttributes.Any(a => a.Type.Equals(typeof(ExperimentalAttribute)))); + } + + [Test] + public void ExperimentalReferencesAreSuppressedWithoutGraduatingOrPromotingTypes() + { + MockHelpers.LoadMockGenerator(); + var dependency = InputFactory.Experimental(InputFactory.Model("Dependency"), "DEP001"); + var model = InputFactory.Model("Payload", properties: [InputFactory.Property("dependency", InputFactory.Array(dependency))]); + var provider = CodeModelGenerator.Instance.TypeFactory.CreateModel(model)!; + + Assert.IsFalse(provider.Attributes.Any(a => a.Type.Equals(typeof(ExperimentalAttribute)))); + Assert.AreEqual(Snippet.Literal("DEP001").ToDisplayString(), provider.DisabledFileWarnings.Single().Code.ToDisplayString()); + Assert.IsTrue(CodeModelGenerator.Instance.TypeFactory.CreateModel(dependency)!.Attributes.Any(a => a.Type.Equals(typeof(ExperimentalAttribute)))); + } + + [Test] + public void ExperimentalApiVersionMembers() + { + MockHelpers.LoadMockGenerator(); + var input = InputFactory.StringEnum("Versions", [("2024-01-01", "2024-01-01")], usage: InputModelTypeUsage.ApiVersionEnum); + InputFactory.Experimental(input.Values[0], "VERSION001"); + var provider = CodeModelGenerator.Instance.TypeFactory.CreateEnum(input)!; + + Assert.AreEqual(Snippet.Literal("VERSION001").ToDisplayString(), + provider.EnumValues.Single().Field.Attributes.Single(a => a.Type.Equals(typeof(ExperimentalAttribute))).Arguments[0].ToDisplayString()); + } + + [TestCase("MODEL001")] + [TestCase(null)] + public void ExperimentalModelDependenciesDoNotControlPublicStatus(string? diagnosticId) + { + MockHelpers.LoadMockGenerator(); + var input = InputFactory.Experimental(InputFactory.Model("Payload"), diagnosticId, "DEP001", "DEP001"); + var provider = CodeModelGenerator.Instance.TypeFactory.CreateModel(input)!; + + Assert.AreEqual(diagnosticId is null ? 0 : 1, provider.Attributes.Count(a => a.Type.Equals(typeof(ExperimentalAttribute)))); + Assert.AreEqual(1, provider.DisabledFileWarnings.Count(s => s.Code.ToDisplayString() == Snippet.Literal("DEP001").ToDisplayString())); + } + [SetUp] public void Setup() { diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/common/InputFactory.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/common/InputFactory.cs index 8c53ad05e54..d834c0e0adb 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/common/InputFactory.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/common/InputFactory.cs @@ -12,6 +12,24 @@ namespace Microsoft.TypeSpec.Generator.Tests.Common { public static class InputFactory { + public static T Experimental(T type, string? diagnosticId, params string[] dependsOn) where T : InputType + { + type.Experimental = new InputExperimentalDetails(diagnosticId, dependsOn); + return type; + } + + public static InputModelProperty Experimental(InputModelProperty property, string? diagnosticId, params string[] dependsOn) + { + property.Experimental = new InputExperimentalDetails(diagnosticId, dependsOn); + return property; + } + + public static InputClient Experimental(InputClient client, string? diagnosticId, params string[] dependsOn) + { + client.Experimental = new InputExperimentalDetails(diagnosticId, dependsOn); + return client; + } + public static class EnumMember { public static InputEnumTypeValue Int32(string name, int value, InputEnumType enumType, bool isExactName = false) diff --git a/packages/http-client-csharp/generator/TestProjects/Local.Tests/CustomizationTests.cs b/packages/http-client-csharp/generator/TestProjects/Local.Tests/CustomizationTests.cs index b995d6d61fb..5ccf30fcc8e 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local.Tests/CustomizationTests.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local.Tests/CustomizationTests.cs @@ -1,6 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; +using System.ClientModel.Primitives; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using NUnit.Framework; @@ -10,6 +13,82 @@ namespace TestProjects.Local.Tests { public class CustomizationTests { + [TestCase("GetNotebookResult", "GetNotebookResponse")] + [TestCase("GetWidgetMetricsResult", "GetWidgetMetricsResponse")] + [TestCase("ListWithContinuationTokenHeaderResponseResult", "ListWithContinuationTokenHeaderResponseResponse")] + [TestCase("ListWithContinuationTokenResult", "ListWithContinuationTokenResponse")] + [TestCase("ListWithNextLinkResult", "ListWithNextLinkResponse")] + [TestCase("ListWithStringNextLinkResult", "ListWithStringNextLinkResponse")] + [TestCase("ReturnsAnonymousModelResult", "ReturnsAnonymousModelResponse")] + [TestCase("LifecycleModel", null)] + [TestCase("PagePreviewDetails", null)] + [TestCase("PreviewDetails", null)] + public void ModelReaderWriterContextRegistersGeneratedModels(string modelName, string? previousName) + { + var modelType = typeof(SampleTypeSpecClient).Assembly.GetType($"SampleTypeSpec.{modelName}"); + Assert.IsNotNull(modelType); + var registeredTypes = typeof(SampleTypeSpecContext).GetCustomAttributesData() + .Where(attribute => attribute.AttributeType == typeof(ModelReaderWriterBuildableAttribute)) + .Select(attribute => (Type)attribute.ConstructorArguments[0].Value!) + .ToArray(); + + Assert.AreEqual(1, registeredTypes.Count(type => type == modelType)); + if (previousName != null) + { + Assert.IsNull(typeof(SampleTypeSpecClient).Assembly.GetType($"SampleTypeSpec.{previousName}")); + Assert.IsFalse(registeredTypes.Any(type => type.Name == previousName)); + } + } + + [TestCase("SampleTypeSpec.PreviewDetails", "SAMPLE0003")] + [TestCase("SampleTypeSpec.PreviewChoice", "SAMPLE0004")] + [TestCase("SampleTypeSpec.PreviewExtensibleChoice", "SAMPLE0005")] + [TestCase("SampleTypeSpec.ExperimentalSamples", "SAMPLE0009")] + [TestCase("SampleTypeSpec.LifecycleModel", null)] + public void ExperimentalTypeDiagnostics(string typeName, string? diagnosticId) + { + var type = typeof(SampleTypeSpecClient).Assembly.GetType(typeName); + Assert.IsNotNull(type); + Assert.AreEqual(diagnosticId, type!.GetCustomAttribute()?.DiagnosticId); + } + + [TestCase("SampleTypeSpec.PreviewChoice", "Two", "SAMPLE0007")] + [TestCase("SampleTypeSpec.PreviewExtensibleChoice", "Two", "SAMPLE0006")] + [TestCase("SampleTypeSpec.LifecycleModel", "Preview", "SAMPLE0008")] + [TestCase("SampleTypeSpec.SampleTypeSpecModelFactory", "PreviewDetails", "SAMPLE0003")] + [TestCase("SampleTypeSpec.PreviewChoice", "One", null)] + [TestCase("SampleTypeSpec.PreviewExtensibleChoice", "One", null)] + [TestCase("SampleTypeSpec.SampleTypeSpecClientOptions+ServiceVersion", "V2024_08_16_Preview", "SAMPLE0010")] + public void ExperimentalMemberDiagnostics(string typeName, string memberName, string? diagnosticId) + { + var type = typeof(SampleTypeSpecClient).Assembly.GetType(typeName); + Assert.IsNotNull(type); + var member = type!.GetMember(memberName).Single(); + Assert.AreEqual(diagnosticId, member.GetCustomAttribute()?.DiagnosticId); + } + + [TestCase("HelloDemo2", "SAMPLE0001", 2)] + [TestCase("HelloDemo2Async", "SAMPLE0001", 2)] + [TestCase("DynamicModelOperation", "SAMPLE0002", 2)] + [TestCase("DynamicModelOperationAsync", "SAMPLE0002", 2)] + [TestCase("SayHi", null, 2)] + [TestCase("SayHiAsync", null, 2)] + [TestCase("CreateHelloDemo2Request", null, 1)] + [TestCase("CreateDynamicModelOperationRequest", null, 1)] + public void ExperimentalOperationDiagnosticsAreScopedToPublicApis(string methodName, string? diagnosticId, int overloadCount) + { + var methods = typeof(SampleTypeSpecClient) + .GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) + .Where(method => method.Name == methodName) + .ToArray(); + + Assert.AreEqual(overloadCount, methods.Length); + foreach (var method in methods) + { + Assert.AreEqual(diagnosticId, method.GetCustomAttribute()?.DiagnosticId); + } + } + [Test] public void ModelNameIsCustomized() { diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/Sample-TypeSpec.tsp b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/Sample-TypeSpec.tsp index 7daa3c98cff..b900c260de4 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/Sample-TypeSpec.tsp +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/Sample-TypeSpec.tsp @@ -4,6 +4,7 @@ import "@typespec/http/streams"; import "@typespec/sse"; import "@typespec/events"; import "@typespec/xml"; +import "@typespec/http-client"; import "@typespec/http-client-csharp"; import "@azure-tools/typespec-client-generator-core"; import "@azure-tools/typespec-azure-core"; @@ -41,9 +42,78 @@ alias SampleOAuth2 = OAuth2Auth<[ enum Versions { `2024-07-16-preview`, + + @TypeSpec.HttpClient.experimental(#{ + emitterScope: "@typespec/http-client-csharp", + diagnosticId: "SAMPLE0010", + }) `2024-08-16-preview`, } +@TypeSpec.HttpClient.experimental(#{ + emitterScope: "@typespec/http-client-csharp", + diagnosticId: "SAMPLE0003", + dependsOn: #["SAMPLE0004"], +}) +model PreviewDetails { + choice: PreviewChoice; +} + +@TypeSpec.HttpClient.experimental(#{ + emitterScope: "@typespec/http-client-csharp", + diagnosticId: "SAMPLE0004", +}) +enum PreviewChoice { + One: "one", + + @TypeSpec.HttpClient.experimental(#{ + emitterScope: "@typespec/http-client-csharp", + diagnosticId: "SAMPLE0007", + }) + Two: "two", +} + +@TypeSpec.HttpClient.experimental(#{ + emitterScope: "@typespec/http-client-csharp", + diagnosticId: "SAMPLE0005", +}) +union PreviewExtensibleChoice { + string, + One: "one", + + @TypeSpec.HttpClient.experimental(#{ + emitterScope: "@typespec/http-client-csharp", + diagnosticId: "SAMPLE0006", + }) + Two: "two", +} + +model LifecycleModel { + @TypeSpec.HttpClient.experimental(#{ + emitterScope: "@typespec/http-client-csharp", + diagnosticId: "SAMPLE0008", + dependsOn: #["SAMPLE0003"], + }) + preview?: PreviewDetails; + + choice: PreviewExtensibleChoice; +} + +@TypeSpec.HttpClient.experimental(#{ + emitterScope: "@typespec/http-client-csharp", + diagnosticId: "SAMPLE0009", +}) +interface ExperimentalSamples { + @route("/experimental") + @get + read(): LifecycleModel; + + @route("/experimental/pages") + @get + @list + list(): Page; +} + @doc("float fixed enum") enum FloatFixedEnumWithIntValue { One: 1.0, @@ -553,6 +623,10 @@ op noContentTypeOverride(info: Wrapper): RoundTripModel; @doc("Return hi in demo2") @get @convenientAPI(true, "csharp") +@TypeSpec.HttpClient.experimental(#{ + emitterScope: "@typespec/http-client-csharp", + diagnosticId: "SAMPLE0001", +}) op helloDemo2(): Thing; @route("/literal") @@ -710,6 +784,11 @@ op EmbeddedParameters(@bodyRoot body: ModelWithEmbeddedNonBodyParameters): void; @route("dynamicModel") @doc("An operation with a dynamic model") @post +@TypeSpec.HttpClient.experimental(#{ + emitterScope: "@typespec/http-client-csharp", + diagnosticId: "SAMPLE0002", + dependsOn: #["SCME0001"], +}) op DynamicModelOperation(@body body: DynamicModel): void; @route("xmlAdvanced") @@ -947,3 +1026,7 @@ op receiveJsonLines(): JsonlStream; @get @route("/streaming/sse/receive") op receiveSse(): SSEStream; + +@route("/experimental/jsonl") +@get +op receiveExperimentalJsonLines(): JsonlStream; diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/CollectionResults/ExperimentalSamplesGetAllAsyncCollectionResult.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/CollectionResults/ExperimentalSamplesGetAllAsyncCollectionResult.cs new file mode 100644 index 00000000000..f59be9a8037 --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/CollectionResults/ExperimentalSamplesGetAllAsyncCollectionResult.cs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Threading.Tasks; + +#pragma warning disable SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0009 // This generated code depends on experimental functionality. +namespace SampleTypeSpec +{ + internal partial class ExperimentalSamplesGetAllAsyncCollectionResult : AsyncCollectionResult + { + private readonly ExperimentalSamples _client; + private readonly RequestOptions _options; + + /// Initializes a new instance of ExperimentalSamplesGetAllAsyncCollectionResult, which is used to iterate over the pages of a collection. + /// The ExperimentalSamples client used to send requests. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + public ExperimentalSamplesGetAllAsyncCollectionResult(ExperimentalSamples client, RequestOptions options) + { + _client = client; + _options = options; + } + + /// Gets the raw pages of the collection. + /// The raw pages of the collection. + public override async IAsyncEnumerable GetRawPagesAsync() + { + PipelineMessage message = _client.CreateGetAllRequest(_options); + yield return await GetNextResponseAsync(message).ConfigureAwait(false); + } + + /// Gets the continuation token from the specified page. + /// + /// The continuation token for the specified page. + public override ContinuationToken GetContinuationToken(ClientResult page) + { + return null; + } + + /// Sends the request in the pipeline message and returns the response. + /// The pipeline message containing the request to send. + private async ValueTask GetNextResponseAsync(PipelineMessage message) + { + return ClientResult.FromResponse(await _client.Pipeline.ProcessMessageAsync(message, _options).ConfigureAwait(false)); + } + } +} +#pragma warning restore SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0009 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/CollectionResults/ExperimentalSamplesGetAllAsyncCollectionResultOfT.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/CollectionResults/ExperimentalSamplesGetAllAsyncCollectionResultOfT.cs new file mode 100644 index 00000000000..562396dbb8c --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/CollectionResults/ExperimentalSamplesGetAllAsyncCollectionResultOfT.cs @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Threading.Tasks; + +#pragma warning disable SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0009 // This generated code depends on experimental functionality. +namespace SampleTypeSpec +{ + internal partial class ExperimentalSamplesGetAllAsyncCollectionResultOfT : AsyncCollectionResult + { + private readonly ExperimentalSamples _client; + private readonly RequestOptions _options; + + /// Initializes a new instance of ExperimentalSamplesGetAllAsyncCollectionResultOfT, which is used to iterate over the pages of a collection. + /// The ExperimentalSamples client used to send requests. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + public ExperimentalSamplesGetAllAsyncCollectionResultOfT(ExperimentalSamples client, RequestOptions options) + { + _client = client; + _options = options; + } + + /// Gets the raw pages of the collection. + /// The raw pages of the collection. + public override async IAsyncEnumerable GetRawPagesAsync() + { + PipelineMessage message = _client.CreateGetAllRequest(_options); + yield return await GetNextResponseAsync(message).ConfigureAwait(false); + } + + /// Gets the continuation token from the specified page. + /// + /// The continuation token for the specified page. + public override ContinuationToken GetContinuationToken(ClientResult page) + { + return null; + } + + /// Gets the values from the specified page. + /// + /// The values from the specified page. + protected override async IAsyncEnumerable GetValuesFromPageAsync(ClientResult page) + { + foreach (PreviewDetails item in ((PagePreviewDetails)page).Items) + { + yield return item; + await Task.Yield(); + } + } + + /// Sends the request in the pipeline message and returns the response. + /// The pipeline message containing the request to send. + private async ValueTask GetNextResponseAsync(PipelineMessage message) + { + return ClientResult.FromResponse(await _client.Pipeline.ProcessMessageAsync(message, _options).ConfigureAwait(false)); + } + } +} +#pragma warning restore SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0009 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/CollectionResults/ExperimentalSamplesGetAllCollectionResult.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/CollectionResults/ExperimentalSamplesGetAllCollectionResult.cs new file mode 100644 index 00000000000..36b62d78943 --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/CollectionResults/ExperimentalSamplesGetAllCollectionResult.cs @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; + +#pragma warning disable SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0009 // This generated code depends on experimental functionality. +namespace SampleTypeSpec +{ + internal partial class ExperimentalSamplesGetAllCollectionResult : CollectionResult + { + private readonly ExperimentalSamples _client; + private readonly RequestOptions _options; + + /// Initializes a new instance of ExperimentalSamplesGetAllCollectionResult, which is used to iterate over the pages of a collection. + /// The ExperimentalSamples client used to send requests. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + public ExperimentalSamplesGetAllCollectionResult(ExperimentalSamples client, RequestOptions options) + { + _client = client; + _options = options; + } + + /// Gets the raw pages of the collection. + /// The raw pages of the collection. + public override IEnumerable GetRawPages() + { + PipelineMessage message = _client.CreateGetAllRequest(_options); + yield return GetNextResponse(message); + } + + /// Gets the continuation token from the specified page. + /// + /// The continuation token for the specified page. + public override ContinuationToken GetContinuationToken(ClientResult page) + { + return null; + } + + /// Sends the request in the pipeline message and returns the response. + /// The pipeline message containing the request to send. + private ClientResult GetNextResponse(PipelineMessage message) + { + return ClientResult.FromResponse(_client.Pipeline.ProcessMessage(message, _options)); + } + } +} +#pragma warning restore SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0009 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/CollectionResults/ExperimentalSamplesGetAllCollectionResultOfT.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/CollectionResults/ExperimentalSamplesGetAllCollectionResultOfT.cs new file mode 100644 index 00000000000..8264764d4ca --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/CollectionResults/ExperimentalSamplesGetAllCollectionResultOfT.cs @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; + +#pragma warning disable SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0009 // This generated code depends on experimental functionality. +namespace SampleTypeSpec +{ + internal partial class ExperimentalSamplesGetAllCollectionResultOfT : CollectionResult + { + private readonly ExperimentalSamples _client; + private readonly RequestOptions _options; + + /// Initializes a new instance of ExperimentalSamplesGetAllCollectionResultOfT, which is used to iterate over the pages of a collection. + /// The ExperimentalSamples client used to send requests. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + public ExperimentalSamplesGetAllCollectionResultOfT(ExperimentalSamples client, RequestOptions options) + { + _client = client; + _options = options; + } + + /// Gets the raw pages of the collection. + /// The raw pages of the collection. + public override IEnumerable GetRawPages() + { + PipelineMessage message = _client.CreateGetAllRequest(_options); + yield return GetNextResponse(message); + } + + /// Gets the continuation token from the specified page. + /// + /// The continuation token for the specified page. + public override ContinuationToken GetContinuationToken(ClientResult page) + { + return null; + } + + /// Gets the values from the specified page. + /// + /// The values from the specified page. + protected override IEnumerable GetValuesFromPage(ClientResult page) + { + return ((PagePreviewDetails)page).Items; + } + + /// Sends the request in the pipeline message and returns the response. + /// The pipeline message containing the request to send. + private ClientResult GetNextResponse(PipelineMessage message) + { + return ClientResult.FromResponse(_client.Pipeline.ProcessMessage(message, _options)); + } + } +} +#pragma warning restore SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0009 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/ExperimentalSamples.RestClient.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/ExperimentalSamples.RestClient.cs new file mode 100644 index 00000000000..5aecfa4224c --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/ExperimentalSamples.RestClient.cs @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.ClientModel.Primitives; + +#pragma warning disable SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0009 // This generated code depends on experimental functionality. +namespace SampleTypeSpec +{ + /// + public partial class ExperimentalSamples + { + private static PipelineMessageClassifier _pipelineMessageClassifier200; + + private static PipelineMessageClassifier PipelineMessageClassifier200 => _pipelineMessageClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); + + internal PipelineMessage CreateReadRequest(RequestOptions options) + { + ClientUriBuilder uri = new ClientUriBuilder(); + uri.Reset(_endpoint); + uri.AppendPath("/experimental", false); + PipelineMessage message = Pipeline.CreateMessage(uri.ToUri(), "GET", PipelineMessageClassifier200); + PipelineRequest request = message.Request; + request.Headers.Set("Accept", "application/json"); + message.Apply(options); + return message; + } + + internal PipelineMessage CreateGetAllRequest(RequestOptions options) + { + ClientUriBuilder uri = new ClientUriBuilder(); + uri.Reset(_endpoint); + uri.AppendPath("/experimental/pages", false); + PipelineMessage message = Pipeline.CreateMessage(uri.ToUri(), "GET", PipelineMessageClassifier200); + PipelineRequest request = message.Request; + request.Headers.Set("Accept", "application/json"); + message.Apply(options); + return message; + } + } +} +#pragma warning restore SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0009 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/ExperimentalSamples.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/ExperimentalSamples.cs new file mode 100644 index 00000000000..f45f4ca05b3 --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/ExperimentalSamples.cs @@ -0,0 +1,144 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Diagnostics.CodeAnalysis; +using System.Threading; +using System.Threading.Tasks; + +#pragma warning disable SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0009 // This generated code depends on experimental functionality. +namespace SampleTypeSpec +{ + /// The ExperimentalSamples sub-client. + [Experimental("SAMPLE0009")] + public partial class ExperimentalSamples + { + private readonly Uri _endpoint; + + /// Initializes a new instance of ExperimentalSamples for mocking. + protected ExperimentalSamples() + { + } + + /// Initializes a new instance of ExperimentalSamples. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// Service endpoint. + internal ExperimentalSamples(ClientPipeline pipeline, Uri endpoint) + { + _endpoint = endpoint; + Pipeline = pipeline; + } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public ClientPipeline Pipeline { get; } + + /// + /// [Protocol Method] Read + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual ClientResult Read(RequestOptions options) + { + using PipelineMessage message = CreateReadRequest(options); + return ClientResult.FromResponse(Pipeline.ProcessMessage(message, options)); + } + + /// + /// [Protocol Method] Read + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task ReadAsync(RequestOptions options) + { + using PipelineMessage message = CreateReadRequest(options); + return ClientResult.FromResponse(await Pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + + /// Read. + /// The cancellation token that can be used to cancel the operation. + /// Service returned a non-success status code. + public virtual ClientResult Read(CancellationToken cancellationToken = default) + { + ClientResult result = Read(cancellationToken.ToRequestOptions()); + return ClientResult.FromValue((LifecycleModel)result, result.GetRawResponse()); + } + + /// Read. + /// The cancellation token that can be used to cancel the operation. + /// Service returned a non-success status code. + public virtual async Task> ReadAsync(CancellationToken cancellationToken = default) + { + ClientResult result = await ReadAsync(cancellationToken.ToRequestOptions()).ConfigureAwait(false); + return ClientResult.FromValue((LifecycleModel)result, result.GetRawResponse()); + } + + /// + /// [Protocol Method] GetAll + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual CollectionResult GetAll(RequestOptions options) + { + return new ExperimentalSamplesGetAllCollectionResult(this, options); + } + + /// + /// [Protocol Method] GetAll + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual AsyncCollectionResult GetAllAsync(RequestOptions options) + { + return new ExperimentalSamplesGetAllAsyncCollectionResult(this, options); + } + + /// GetAll. + /// The cancellation token that can be used to cancel the operation. + /// Service returned a non-success status code. + public virtual CollectionResult GetAll(CancellationToken cancellationToken = default) + { + return new ExperimentalSamplesGetAllCollectionResultOfT(this, cancellationToken.ToRequestOptions()); + } + + /// GetAll. + /// The cancellation token that can be used to cancel the operation. + /// Service returned a non-success status code. + public virtual AsyncCollectionResult GetAllAsync(CancellationToken cancellationToken = default) + { + return new ExperimentalSamplesGetAllAsyncCollectionResultOfT(this, cancellationToken.ToRequestOptions()); + } + } +} +#pragma warning restore SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0009 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/LifecycleModel.Serialization.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/LifecycleModel.Serialization.cs new file mode 100644 index 00000000000..c17e51fd071 --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/LifecycleModel.Serialization.cs @@ -0,0 +1,172 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +#pragma warning disable SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0005 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0008 // This generated code depends on experimental functionality. +namespace SampleTypeSpec +{ + /// The LifecycleModel. + public partial class LifecycleModel : IJsonModel + { + /// Initializes a new instance of for deserialization. + internal LifecycleModel() + { + } + + /// The data to parse. + /// The client options for reading and writing models. + protected virtual LifecycleModel PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options) + { + string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + switch (format) + { + case "J": + using (JsonDocument document = JsonDocument.Parse(data, ModelSerializationExtensions.JsonDocumentOptions)) + { + return DeserializeLifecycleModel(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(LifecycleModel)} does not support reading '{options.Format}' format."); + } + } + + /// The client options for reading and writing models. + protected virtual BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options) + { + string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options, SampleTypeSpecContext.Default); + default: + throw new FormatException($"The model {nameof(LifecycleModel)} does not support writing '{options.Format}' format."); + } + } + + /// The client options for reading and writing models. + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) => PersistableModelWriteCore(options); + + /// The data to parse. + /// The client options for reading and writing models. + LifecycleModel IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) => PersistableModelCreateCore(data, options); + + /// The client options for reading and writing models. + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// The to deserialize the from. + public static explicit operator LifecycleModel(ClientResult result) + { + PipelineResponse response = result.GetRawResponse(); + using JsonDocument document = JsonDocument.Parse(response.Content, ModelSerializationExtensions.JsonDocumentOptions); + return DeserializeLifecycleModel(document.RootElement, ModelSerializationExtensions.WireOptions); + } + + /// The JSON writer. + /// The client options for reading and writing models. + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteStartObject(); + JsonModelWriteCore(writer, options); + writer.WriteEndObject(); + } + + /// The JSON writer. + /// The client options for reading and writing models. + protected virtual void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(LifecycleModel)} does not support writing '{format}' format."); + } + if (Optional.IsDefined(Preview)) + { + writer.WritePropertyName("preview"u8); + writer.WriteObjectValue(Preview, options); + } + writer.WritePropertyName("choice"u8); + writer.WriteStringValue(Choice.ToString()); + if (options.Format != "W" && _additionalBinaryDataProperties != null) + { + foreach (var item in _additionalBinaryDataProperties) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + } + + /// The JSON reader. + /// The client options for reading and writing models. + LifecycleModel IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) => JsonModelCreateCore(ref reader, options); + + /// The JSON reader. + /// The client options for reading and writing models. + protected virtual LifecycleModel JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(LifecycleModel)} does not support reading '{format}' format."); + } + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeLifecycleModel(document.RootElement, options); + } + + /// The JSON element to deserialize. + /// The client options for reading and writing models. + internal static LifecycleModel DeserializeLifecycleModel(JsonElement element, ModelReaderWriterOptions options) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + PreviewDetails preview = default; + PreviewExtensibleChoice choice = default; + IDictionary additionalBinaryDataProperties = new ChangeTrackingDictionary(); + foreach (var prop in element.EnumerateObject()) + { + if (prop.NameEquals("preview"u8)) + { + if (prop.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + preview = PreviewDetails.DeserializePreviewDetails(prop.Value, options); + continue; + } + if (prop.NameEquals("choice"u8)) + { + choice = new PreviewExtensibleChoice(prop.Value.GetString()); + continue; + } + if (options.Format != "W") + { + additionalBinaryDataProperties.Add(prop.Name, prop.Value.GetUtf8Bytes()); + } + } + return new LifecycleModel(preview, choice, additionalBinaryDataProperties); + } + } +} +#pragma warning restore SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0005 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0008 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/LifecycleModel.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/LifecycleModel.cs new file mode 100644 index 00000000000..3090e862234 --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/LifecycleModel.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +#pragma warning disable SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0005 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0008 // This generated code depends on experimental functionality. +namespace SampleTypeSpec +{ + /// The LifecycleModel. + public partial class LifecycleModel + { + /// Keeps track of any properties unknown to the library. + private protected readonly IDictionary _additionalBinaryDataProperties; + + /// Initializes a new instance of . + /// + internal LifecycleModel(PreviewExtensibleChoice choice) + { + Choice = choice; + } + + /// Initializes a new instance of . + /// + /// + /// Keeps track of any properties unknown to the library. + internal LifecycleModel(PreviewDetails preview, PreviewExtensibleChoice choice, IDictionary additionalBinaryDataProperties) + { + Preview = preview; + Choice = choice; + _additionalBinaryDataProperties = additionalBinaryDataProperties; + } + + /// Gets the Preview. + [Experimental("SAMPLE0008")] + public PreviewDetails Preview { get; } + + /// Gets the Choice. + public PreviewExtensibleChoice Choice { get; } + } +} +#pragma warning restore SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0005 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0008 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PagePreviewDetails.Serialization.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PagePreviewDetails.Serialization.cs new file mode 100644 index 00000000000..6f178c4c0e1 --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PagePreviewDetails.Serialization.cs @@ -0,0 +1,163 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +#pragma warning disable SAMPLE0003 // This generated code depends on experimental functionality. +namespace SampleTypeSpec +{ + /// The PagePreviewDetails. + internal partial class PagePreviewDetails : IJsonModel + { + /// Initializes a new instance of for deserialization. + internal PagePreviewDetails() + { + } + + /// The data to parse. + /// The client options for reading and writing models. + protected virtual PagePreviewDetails PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options) + { + string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + switch (format) + { + case "J": + using (JsonDocument document = JsonDocument.Parse(data, ModelSerializationExtensions.JsonDocumentOptions)) + { + return DeserializePagePreviewDetails(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(PagePreviewDetails)} does not support reading '{options.Format}' format."); + } + } + + /// The client options for reading and writing models. + protected virtual BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options) + { + string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options, SampleTypeSpecContext.Default); + default: + throw new FormatException($"The model {nameof(PagePreviewDetails)} does not support writing '{options.Format}' format."); + } + } + + /// The client options for reading and writing models. + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) => PersistableModelWriteCore(options); + + /// The data to parse. + /// The client options for reading and writing models. + PagePreviewDetails IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) => PersistableModelCreateCore(data, options); + + /// The client options for reading and writing models. + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// The to deserialize the from. + public static explicit operator PagePreviewDetails(ClientResult result) + { + PipelineResponse response = result.GetRawResponse(); + using JsonDocument document = JsonDocument.Parse(response.Content, ModelSerializationExtensions.JsonDocumentOptions); + return DeserializePagePreviewDetails(document.RootElement, ModelSerializationExtensions.WireOptions); + } + + /// The JSON writer. + /// The client options for reading and writing models. + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteStartObject(); + JsonModelWriteCore(writer, options); + writer.WriteEndObject(); + } + + /// The JSON writer. + /// The client options for reading and writing models. + protected virtual void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(PagePreviewDetails)} does not support writing '{format}' format."); + } + writer.WritePropertyName("items"u8); + writer.WriteStartArray(); + foreach (PreviewDetails item in Items) + { + writer.WriteObjectValue(item, options); + } + writer.WriteEndArray(); + if (options.Format != "W" && _additionalBinaryDataProperties != null) + { + foreach (var item in _additionalBinaryDataProperties) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + } + + /// The JSON reader. + /// The client options for reading and writing models. + PagePreviewDetails IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) => JsonModelCreateCore(ref reader, options); + + /// The JSON reader. + /// The client options for reading and writing models. + protected virtual PagePreviewDetails JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(PagePreviewDetails)} does not support reading '{format}' format."); + } + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializePagePreviewDetails(document.RootElement, options); + } + + /// The JSON element to deserialize. + /// The client options for reading and writing models. + internal static PagePreviewDetails DeserializePagePreviewDetails(JsonElement element, ModelReaderWriterOptions options) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + IList items = default; + IDictionary additionalBinaryDataProperties = new ChangeTrackingDictionary(); + foreach (var prop in element.EnumerateObject()) + { + if (prop.NameEquals("items"u8)) + { + List array = new List(); + foreach (var item in prop.Value.EnumerateArray()) + { + array.Add(PreviewDetails.DeserializePreviewDetails(item, options)); + } + items = array; + continue; + } + if (options.Format != "W") + { + additionalBinaryDataProperties.Add(prop.Name, prop.Value.GetUtf8Bytes()); + } + } + return new PagePreviewDetails(items, additionalBinaryDataProperties); + } + } +} +#pragma warning restore SAMPLE0003 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PagePreviewDetails.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PagePreviewDetails.cs new file mode 100644 index 00000000000..9addb6b64f2 --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PagePreviewDetails.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Linq; + +#pragma warning disable SAMPLE0003 // This generated code depends on experimental functionality. +namespace SampleTypeSpec +{ + /// The PagePreviewDetails. + internal partial class PagePreviewDetails + { + /// Keeps track of any properties unknown to the library. + private protected readonly IDictionary _additionalBinaryDataProperties; + + /// Initializes a new instance of . + /// + internal PagePreviewDetails(IEnumerable items) + { + Items = items.ToList(); + } + + /// Initializes a new instance of . + /// + /// Keeps track of any properties unknown to the library. + internal PagePreviewDetails(IList items, IDictionary additionalBinaryDataProperties) + { + Items = items; + _additionalBinaryDataProperties = additionalBinaryDataProperties; + } + + /// Gets the Items. + public IList Items { get; } + } +} +#pragma warning restore SAMPLE0003 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PreviewChoice.Serialization.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PreviewChoice.Serialization.cs new file mode 100644 index 00000000000..e96882ea96a --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PreviewChoice.Serialization.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +#pragma warning disable SAMPLE0004 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0007 // This generated code depends on experimental functionality. +namespace SampleTypeSpec +{ + internal static partial class PreviewChoiceExtensions + { + /// The value to serialize. + public static string ToSerialString(this PreviewChoice value) => value switch + { + PreviewChoice.One => "one", + PreviewChoice.Two => "two", + _ => throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown PreviewChoice value.") + }; + + /// The value to deserialize. + public static PreviewChoice ToPreviewChoice(this string value) + { + if (StringComparer.OrdinalIgnoreCase.Equals(value, "one")) + { + return PreviewChoice.One; + } + if (StringComparer.OrdinalIgnoreCase.Equals(value, "two")) + { + return PreviewChoice.Two; + } + throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown PreviewChoice value."); + } + } +} +#pragma warning restore SAMPLE0004 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0007 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PreviewChoice.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PreviewChoice.cs new file mode 100644 index 00000000000..9656d887166 --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PreviewChoice.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Diagnostics.CodeAnalysis; + +#pragma warning disable SAMPLE0004 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0007 // This generated code depends on experimental functionality. +namespace SampleTypeSpec +{ + /// + [Experimental("SAMPLE0004")] + public enum PreviewChoice + { + /// One. + One, + /// Two. + [Experimental("SAMPLE0007")] + Two + } +} +#pragma warning restore SAMPLE0004 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0007 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PreviewDetails.Serialization.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PreviewDetails.Serialization.cs new file mode 100644 index 00000000000..d7e75966c6d --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PreviewDetails.Serialization.cs @@ -0,0 +1,146 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +#pragma warning disable SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0004 // This generated code depends on experimental functionality. +namespace SampleTypeSpec +{ + /// The PreviewDetails. + public partial class PreviewDetails : IJsonModel + { + /// Initializes a new instance of for deserialization. + internal PreviewDetails() + { + } + + /// The data to parse. + /// The client options for reading and writing models. + protected virtual PreviewDetails PersistableModelCreateCore(BinaryData data, ModelReaderWriterOptions options) + { + string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + switch (format) + { + case "J": + using (JsonDocument document = JsonDocument.Parse(data, ModelSerializationExtensions.JsonDocumentOptions)) + { + return DeserializePreviewDetails(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(PreviewDetails)} does not support reading '{options.Format}' format."); + } + } + + /// The client options for reading and writing models. + protected virtual BinaryData PersistableModelWriteCore(ModelReaderWriterOptions options) + { + string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options, SampleTypeSpecContext.Default); + default: + throw new FormatException($"The model {nameof(PreviewDetails)} does not support writing '{options.Format}' format."); + } + } + + /// The client options for reading and writing models. + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) => PersistableModelWriteCore(options); + + /// The data to parse. + /// The client options for reading and writing models. + PreviewDetails IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) => PersistableModelCreateCore(data, options); + + /// The client options for reading and writing models. + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// The JSON writer. + /// The client options for reading and writing models. + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteStartObject(); + JsonModelWriteCore(writer, options); + writer.WriteEndObject(); + } + + /// The JSON writer. + /// The client options for reading and writing models. + protected virtual void JsonModelWriteCore(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(PreviewDetails)} does not support writing '{format}' format."); + } + writer.WritePropertyName("choice"u8); + writer.WriteStringValue(Choice.ToSerialString()); + if (options.Format != "W" && _additionalBinaryDataProperties != null) + { + foreach (var item in _additionalBinaryDataProperties) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + } + + /// The JSON reader. + /// The client options for reading and writing models. + PreviewDetails IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) => JsonModelCreateCore(ref reader, options); + + /// The JSON reader. + /// The client options for reading and writing models. + protected virtual PreviewDetails JsonModelCreateCore(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + string format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(PreviewDetails)} does not support reading '{format}' format."); + } + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializePreviewDetails(document.RootElement, options); + } + + /// The JSON element to deserialize. + /// The client options for reading and writing models. + internal static PreviewDetails DeserializePreviewDetails(JsonElement element, ModelReaderWriterOptions options) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + PreviewChoice choice = default; + IDictionary additionalBinaryDataProperties = new ChangeTrackingDictionary(); + foreach (var prop in element.EnumerateObject()) + { + if (prop.NameEquals("choice"u8)) + { + choice = prop.Value.GetString().ToPreviewChoice(); + continue; + } + if (options.Format != "W") + { + additionalBinaryDataProperties.Add(prop.Name, prop.Value.GetUtf8Bytes()); + } + } + return new PreviewDetails(choice, additionalBinaryDataProperties); + } + } +} +#pragma warning restore SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0004 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PreviewDetails.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PreviewDetails.cs new file mode 100644 index 00000000000..f4bea99bc4d --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PreviewDetails.cs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +#pragma warning disable SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0004 // This generated code depends on experimental functionality. +namespace SampleTypeSpec +{ + /// The PreviewDetails. + [Experimental("SAMPLE0003")] + public partial class PreviewDetails + { + /// Keeps track of any properties unknown to the library. + private protected readonly IDictionary _additionalBinaryDataProperties; + + /// Initializes a new instance of . + /// + internal PreviewDetails(PreviewChoice choice) + { + Choice = choice; + } + + /// Initializes a new instance of . + /// + /// Keeps track of any properties unknown to the library. + internal PreviewDetails(PreviewChoice choice, IDictionary additionalBinaryDataProperties) + { + Choice = choice; + _additionalBinaryDataProperties = additionalBinaryDataProperties; + } + + /// Gets the Choice. + public PreviewChoice Choice { get; } + } +} +#pragma warning restore SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0004 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PreviewExtensibleChoice.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PreviewExtensibleChoice.cs new file mode 100644 index 00000000000..2af0806965c --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/PreviewExtensibleChoice.cs @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; + +#pragma warning disable SAMPLE0005 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0006 // This generated code depends on experimental functionality. +namespace SampleTypeSpec +{ + /// + [Experimental("SAMPLE0005")] + public readonly partial struct PreviewExtensibleChoice : IEquatable + { + private readonly string _value; + private const string OneValue = "one"; + private const string TwoValue = "two"; + + /// Initializes a new instance of . + /// The value. + /// is null. + public PreviewExtensibleChoice(string value) + { + Argument.AssertNotNull(value, nameof(value)); + + _value = value; + } + + /// Gets the One. + public static PreviewExtensibleChoice One { get; } = new PreviewExtensibleChoice(OneValue); + + /// Gets the Two. + [Experimental("SAMPLE0006")] + public static PreviewExtensibleChoice Two { get; } = new PreviewExtensibleChoice(TwoValue); + + /// Determines if two values are the same. + /// The left value to compare. + /// The right value to compare. + public static bool operator ==(PreviewExtensibleChoice left, PreviewExtensibleChoice right) => left.Equals(right); + + /// Determines if two values are not the same. + /// The left value to compare. + /// The right value to compare. + public static bool operator !=(PreviewExtensibleChoice left, PreviewExtensibleChoice right) => !left.Equals(right); + + /// Converts a string to a . + /// The value. + public static implicit operator PreviewExtensibleChoice(string value) => new PreviewExtensibleChoice(value); + + /// Converts a string to a . + /// The value. + public static implicit operator PreviewExtensibleChoice?(string value) => value == null ? null : new PreviewExtensibleChoice(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is PreviewExtensibleChoice other && Equals(other); + + /// + public bool Equals(PreviewExtensibleChoice other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value != null ? StringComparer.InvariantCultureIgnoreCase.GetHashCode(_value) : 0; + + /// + public override string ToString() => _value; + } +} +#pragma warning restore SAMPLE0005 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0006 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/SampleTypeSpecContext.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/SampleTypeSpecContext.cs index 7cf48210f0d..18e7df9fec8 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/SampleTypeSpecContext.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Models/SampleTypeSpecContext.cs @@ -21,6 +21,7 @@ namespace SampleTypeSpec [ModelReaderWriterBuildable(typeof(Friend))] [ModelReaderWriterBuildable(typeof(GetNotebookResult))] [ModelReaderWriterBuildable(typeof(GetWidgetMetricsResult))] + [ModelReaderWriterBuildable(typeof(LifecycleModel))] [ModelReaderWriterBuildable(typeof(ListWithContinuationTokenHeaderResponseResult))] [ModelReaderWriterBuildable(typeof(ListWithContinuationTokenResult))] [ModelReaderWriterBuildable(typeof(ListWithNextLinkResult))] @@ -28,9 +29,13 @@ namespace SampleTypeSpec [ModelReaderWriterBuildable(typeof(ModelWithEmbeddedNonBodyParameters))] [ModelReaderWriterBuildable(typeof(ModelWithRequiredNullableProperties))] [ModelReaderWriterBuildable(typeof(NullableDynamicModel))] + [ModelReaderWriterBuildable(typeof(PagePreviewDetails))] [ModelReaderWriterBuildable(typeof(PageThing))] [ModelReaderWriterBuildable(typeof(Pet))] [ModelReaderWriterBuildable(typeof(Plant))] +#pragma warning disable SAMPLE0003 // global::SampleTypeSpec.PreviewDetails is experimental and may change in future versions. + [ModelReaderWriterBuildable(typeof(PreviewDetails))] +#pragma warning restore SAMPLE0003 // global::SampleTypeSpec.PreviewDetails is experimental and may change in future versions. [ModelReaderWriterBuildable(typeof(RenamedModelCustom))] [ModelReaderWriterBuildable(typeof(ReturnsAnonymousModelResult))] [ModelReaderWriterBuildable(typeof(RoundTripModel))] diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecClient.RestClient.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecClient.RestClient.cs index 23707366819..73241c04026 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecClient.RestClient.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecClient.RestClient.cs @@ -9,6 +9,8 @@ using System.ClientModel; using System.ClientModel.Primitives; +#pragma warning disable SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0009 // This generated code depends on experimental functionality. namespace SampleTypeSpec { /// @@ -411,6 +413,7 @@ internal PipelineMessage CreateEmbeddedParametersRequest(string requiredHeader, return message; } +#pragma warning disable SCME0001 // This generated code depends on experimental functionality. internal PipelineMessage CreateDynamicModelOperationRequest(BinaryContent content, RequestOptions options) { ClientUriBuilder uri = new ClientUriBuilder(); @@ -423,6 +426,7 @@ internal PipelineMessage CreateDynamicModelOperationRequest(BinaryContent conten message.Apply(options); return message; } +#pragma warning restore SCME0001 // This generated code depends on experimental functionality. internal PipelineMessage CreateGetXmlAdvancedModelRequest(RequestOptions options) { @@ -499,5 +503,19 @@ internal PipelineMessage CreateReceiveSseRequest(RequestOptions options) message.Apply(options); return message; } + + internal PipelineMessage CreateReceiveExperimentalJsonLinesRequest(RequestOptions options) + { + ClientUriBuilder uri = new ClientUriBuilder(); + uri.Reset(_endpoint); + uri.AppendPath("/experimental/jsonl", false); + PipelineMessage message = Pipeline.CreateMessage(uri.ToUri(), "GET", PipelineMessageClassifier200); + PipelineRequest request = message.Request; + request.Headers.Set("Accept", "application/jsonl"); + message.Apply(options); + return message; + } } } +#pragma warning restore SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0009 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecClient.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecClient.cs index 7dd2a166c7d..3d4b6fc6c08 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecClient.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecClient.cs @@ -16,6 +16,8 @@ using System.Threading.Tasks; using SampleTypeSpec.Models.Custom; +#pragma warning disable SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0009 // This generated code depends on experimental functionality. namespace SampleTypeSpec { /// This is a sample typespec project. @@ -34,6 +36,7 @@ public partial class SampleTypeSpecClient } }; private readonly string _apiVersion; + private ExperimentalSamples _cachedExperimentalSamples; private AnimalOperations _cachedAnimalOperations; private PetOperations _cachedPetOperations; private DogOperations _cachedDogOperations; @@ -363,6 +366,7 @@ public virtual async Task> NoContentTypeAsync(Wrapp /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// Service returned a non-success status code. /// The response returned from the service. + [Experimental("SAMPLE0001")] public virtual ClientResult HelloDemo2(RequestOptions options) { using PipelineMessage message = CreateHelloDemo2Request(options); @@ -380,6 +384,7 @@ public virtual ClientResult HelloDemo2(RequestOptions options) /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// Service returned a non-success status code. /// The response returned from the service. + [Experimental("SAMPLE0001")] public virtual async Task HelloDemo2Async(RequestOptions options) { using PipelineMessage message = CreateHelloDemo2Request(options); @@ -389,6 +394,7 @@ public virtual async Task HelloDemo2Async(RequestOptions options) /// Return hi in demo2. /// The cancellation token that can be used to cancel the operation. /// Service returned a non-success status code. + [Experimental("SAMPLE0001")] public virtual ClientResult HelloDemo2(CancellationToken cancellationToken = default) { ClientResult result = HelloDemo2(cancellationToken.ToRequestOptions()); @@ -398,6 +404,7 @@ public virtual ClientResult HelloDemo2(CancellationToken cancellationToke /// Return hi in demo2. /// The cancellation token that can be used to cancel the operation. /// Service returned a non-success status code. + [Experimental("SAMPLE0001")] public virtual async Task> HelloDemo2Async(CancellationToken cancellationToken = default) { ClientResult result = await HelloDemo2Async(cancellationToken.ToRequestOptions()).ConfigureAwait(false); @@ -1693,6 +1700,8 @@ public virtual async Task EmbeddedParametersAsync(ModelWithEmbedde /// is null. /// Service returned a non-success status code. /// The response returned from the service. +#pragma warning disable SCME0001 // This generated code depends on experimental functionality. + [Experimental("SAMPLE0002")] public virtual ClientResult DynamicModelOperation(BinaryContent content, RequestOptions options = null) { Argument.AssertNotNull(content, nameof(content)); @@ -1700,6 +1709,7 @@ public virtual ClientResult DynamicModelOperation(BinaryContent content, Request using PipelineMessage message = CreateDynamicModelOperationRequest(content, options); return ClientResult.FromResponse(Pipeline.ProcessMessage(message, options)); } +#pragma warning restore SCME0001 // This generated code depends on experimental functionality. /// /// [Protocol Method] An operation with a dynamic model @@ -1714,6 +1724,8 @@ public virtual ClientResult DynamicModelOperation(BinaryContent content, Request /// is null. /// Service returned a non-success status code. /// The response returned from the service. +#pragma warning disable SCME0001 // This generated code depends on experimental functionality. + [Experimental("SAMPLE0002")] public virtual async Task DynamicModelOperationAsync(BinaryContent content, RequestOptions options = null) { Argument.AssertNotNull(content, nameof(content)); @@ -1721,30 +1733,37 @@ public virtual async Task DynamicModelOperationAsync(BinaryContent using PipelineMessage message = CreateDynamicModelOperationRequest(content, options); return ClientResult.FromResponse(await Pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); } +#pragma warning restore SCME0001 // This generated code depends on experimental functionality. /// An operation with a dynamic model. /// /// The cancellation token that can be used to cancel the operation. /// is null. /// Service returned a non-success status code. +#pragma warning disable SCME0001 // This generated code depends on experimental functionality. + [Experimental("SAMPLE0002")] public virtual ClientResult DynamicModelOperation(DynamicModel body, CancellationToken cancellationToken = default) { Argument.AssertNotNull(body, nameof(body)); return DynamicModelOperation(body, cancellationToken.ToRequestOptions()); } +#pragma warning restore SCME0001 // This generated code depends on experimental functionality. /// An operation with a dynamic model. /// /// The cancellation token that can be used to cancel the operation. /// is null. /// Service returned a non-success status code. +#pragma warning disable SCME0001 // This generated code depends on experimental functionality. + [Experimental("SAMPLE0002")] public virtual async Task DynamicModelOperationAsync(DynamicModel body, CancellationToken cancellationToken = default) { Argument.AssertNotNull(body, nameof(body)); return await DynamicModelOperationAsync(body, cancellationToken.ToRequestOptions()).ConfigureAwait(false); } +#pragma warning restore SCME0001 // This generated code depends on experimental functionality. /// /// [Protocol Method] Get an advanced XML model with various property types @@ -2053,6 +2072,40 @@ public virtual async Task>> ReceiveS return AsyncStreamingResult.CreateSse(await Pipeline.ProcessMessageAsync(message, cancellationToken.ToRequestOptions()).ConfigureAwait(false), (@_, data) => ModelReaderWriter.Read(BinaryData.FromBytes(data.ToArray()), ModelSerializationExtensions.WireOptions, SampleTypeSpecContext.Default), item => item.Data.ToString() == "[DONE]", cancellationToken); } + /// + /// [Protocol Method] ReceiveExperimentalJsonLines + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task> ReceiveExperimentalJsonLinesAsync(RequestOptions options) + { + using PipelineMessage message = CreateReceiveExperimentalJsonLinesRequest(options); + message.BufferResponse = false; + return AsyncStreamingResult.CreateJsonLines(await Pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + + /// ReceiveExperimentalJsonLines. + /// The cancellation token that can be used to cancel the operation. + /// Service returned a non-success status code. + public virtual async Task> ReceiveExperimentalJsonLinesAsync(CancellationToken cancellationToken = default) + { + using PipelineMessage message = CreateReceiveExperimentalJsonLinesRequest(cancellationToken.ToRequestOptions()); + message.BufferResponse = false; + return AsyncStreamingResult.CreateJsonLines(await Pipeline.ProcessMessageAsync(message, cancellationToken.ToRequestOptions()).ConfigureAwait(false), data => ModelReaderWriter.Read(data, ModelSerializationExtensions.WireOptions, SampleTypeSpecContext.Default), cancellationToken); + } + + /// Initializes a new instance of ExperimentalSamples. + public virtual ExperimentalSamples GetExperimentalSamplesClient() + { + return Volatile.Read(ref _cachedExperimentalSamples) ?? Interlocked.CompareExchange(ref _cachedExperimentalSamples, new ExperimentalSamples(Pipeline, _endpoint), null) ?? _cachedExperimentalSamples; + } + /// Initializes a new instance of AnimalOperations. public virtual AnimalOperations GetAnimalOperationsClient() { @@ -2098,3 +2151,5 @@ public virtual Notebooks GetNotebooksClient(string notebook) } } } +#pragma warning restore SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0009 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecClientOptions.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecClientOptions.cs index e26fb92bc89..08db66ff4bd 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecClientOptions.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecClientOptions.cs @@ -10,6 +10,7 @@ using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Configuration; +#pragma warning disable SAMPLE0010 // This generated code depends on experimental functionality. namespace SampleTypeSpec { /// Client options for . @@ -54,7 +55,9 @@ public enum ServiceVersion /// V2024_07_16_Preview. V2024_07_16_Preview = 1, /// V2024_08_16_Preview. + [Experimental("SAMPLE0010")] V2024_08_16_Preview = 2 } } } +#pragma warning restore SAMPLE0010 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecModelFactory.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecModelFactory.cs index 9c7b48fd7d4..64b173bf72e 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecModelFactory.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecModelFactory.cs @@ -12,6 +12,10 @@ using System.Linq; using SampleTypeSpec.Models.Custom; +#pragma warning disable SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0004 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0005 // This generated code depends on experimental functionality. +#pragma warning disable SAMPLE0008 // This generated code depends on experimental functionality. namespace SampleTypeSpec { /// A factory class for creating instances of the models for mocking. @@ -438,6 +442,24 @@ public static StreamingItem StreamingItem(string message = default) return new StreamingItem(message, additionalBinaryDataProperties: null); } + /// The PreviewDetails. + /// + /// A new instance for mocking. + [Experimental("SAMPLE0003")] + public static PreviewDetails PreviewDetails(PreviewChoice choice = default) + { + return new PreviewDetails(choice, additionalBinaryDataProperties: null); + } + + /// The LifecycleModel. + /// + /// + /// A new instance for mocking. + public static LifecycleModel LifecycleModel(PreviewDetails preview = default, PreviewExtensibleChoice choice = default) + { + return new LifecycleModel(preview, choice, additionalBinaryDataProperties: null); + } + /// /// Base animal with discriminator /// Please note this is the abstract base class. The derived classes available for instantiation are: and . @@ -540,3 +562,7 @@ public static NullableDynamicModel NullableDynamicModel(AnotherDynamicModel mode } } } +#pragma warning restore SAMPLE0003 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0004 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0005 // This generated code depends on experimental functionality. +#pragma warning restore SAMPLE0008 // This generated code depends on experimental functionality. diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/tspCodeModel.json b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/tspCodeModel.json index c62e73954c4..3abed6962da 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/tspCodeModel.json +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/tspCodeModel.json @@ -716,12 +716,12 @@ { "$id": "57", "kind": "enum", - "name": "DaysOfWeekExtensibleEnum", + "name": "PreviewChoice", "apiVersions": [ "2024-07-16-preview", "2024-08-16-preview" ], - "crossLanguageDefinitionId": "SampleTypeSpec.DaysOfWeekExtensibleEnum", + "crossLanguageDefinitionId": "SampleTypeSpec.PreviewChoice", "valueType": { "$id": "58", "kind": "string", @@ -733,8 +733,8 @@ { "$id": "59", "kind": "enumvalue", - "name": "Monday", - "value": "Monday", + "name": "One", + "value": "one", "valueType": { "$ref": "58" }, @@ -747,8 +747,8 @@ { "$id": "60", "kind": "enumvalue", - "name": "Tuesday", - "value": "Tuesday", + "name": "Two", + "value": "two", "valueType": { "$ref": "58" }, @@ -756,74 +756,196 @@ "$ref": "57" }, "decorators": [], + "isExactName": false, + "experimental": { + "diagnosticId": "SAMPLE0007", + "dependsOn": [] + } + } + ], + "namespace": "SampleTypeSpec", + "isFixed": true, + "isFlags": false, + "usage": "Output,Json", + "decorators": [], + "isExactName": false, + "experimental": { + "diagnosticId": "SAMPLE0004", + "dependsOn": [] + } + }, + { + "$id": "61", + "kind": "enum", + "name": "PreviewExtensibleChoice", + "apiVersions": [ + "2024-07-16-preview", + "2024-08-16-preview" + ], + "crossLanguageDefinitionId": "SampleTypeSpec.PreviewExtensibleChoice", + "valueType": { + "$id": "62", + "kind": "string", + "name": "string", + "crossLanguageDefinitionId": "TypeSpec.string", + "decorators": [] + }, + "values": [ + { + "$id": "63", + "kind": "enumvalue", + "name": "One", + "value": "one", + "valueType": { + "$ref": "62" + }, + "enumType": { + "$ref": "61" + }, + "decorators": [], + "isExactName": false + }, + { + "$id": "64", + "kind": "enumvalue", + "name": "Two", + "value": "two", + "valueType": { + "$ref": "62" + }, + "enumType": { + "$ref": "61" + }, + "decorators": [], + "isExactName": false, + "experimental": { + "diagnosticId": "SAMPLE0006", + "dependsOn": [] + } + } + ], + "namespace": "SampleTypeSpec", + "isFixed": false, + "isFlags": false, + "usage": "Output,Json", + "decorators": [], + "isExactName": false, + "experimental": { + "diagnosticId": "SAMPLE0005", + "dependsOn": [] + } + }, + { + "$id": "65", + "kind": "enum", + "name": "DaysOfWeekExtensibleEnum", + "apiVersions": [ + "2024-07-16-preview", + "2024-08-16-preview" + ], + "crossLanguageDefinitionId": "SampleTypeSpec.DaysOfWeekExtensibleEnum", + "valueType": { + "$id": "66", + "kind": "string", + "name": "string", + "crossLanguageDefinitionId": "TypeSpec.string", + "decorators": [] + }, + "values": [ + { + "$id": "67", + "kind": "enumvalue", + "name": "Monday", + "value": "Monday", + "valueType": { + "$ref": "66" + }, + "enumType": { + "$ref": "65" + }, + "decorators": [], + "isExactName": false + }, + { + "$id": "68", + "kind": "enumvalue", + "name": "Tuesday", + "value": "Tuesday", + "valueType": { + "$ref": "66" + }, + "enumType": { + "$ref": "65" + }, + "decorators": [], "isExactName": false }, { - "$id": "61", + "$id": "69", "kind": "enumvalue", "name": "Wednesday", "value": "Wednesday", "valueType": { - "$ref": "58" + "$ref": "66" }, "enumType": { - "$ref": "57" + "$ref": "65" }, "decorators": [], "isExactName": false }, { - "$id": "62", + "$id": "70", "kind": "enumvalue", "name": "Thursday", "value": "Thursday", "valueType": { - "$ref": "58" + "$ref": "66" }, "enumType": { - "$ref": "57" + "$ref": "65" }, "decorators": [], "isExactName": false }, { - "$id": "63", + "$id": "71", "kind": "enumvalue", "name": "Friday", "value": "Friday", "valueType": { - "$ref": "58" + "$ref": "66" }, "enumType": { - "$ref": "57" + "$ref": "65" }, "decorators": [], "isExactName": false }, { - "$id": "64", + "$id": "72", "kind": "enumvalue", "name": "Saturday", "value": "Saturday", "valueType": { - "$ref": "58" + "$ref": "66" }, "enumType": { - "$ref": "57" + "$ref": "65" }, "decorators": [], "isExactName": false }, { - "$id": "65", + "$id": "73", "kind": "enumvalue", "name": "Sunday", "value": "Sunday", "valueType": { - "$ref": "58" + "$ref": "66" }, "enumType": { - "$ref": "57" + "$ref": "65" }, "decorators": [], "isExactName": false @@ -837,7 +959,7 @@ "isExactName": false }, { - "$id": "66", + "$id": "74", "kind": "enum", "name": "Versions", "apiVersions": [ @@ -846,7 +968,7 @@ ], "crossLanguageDefinitionId": "SampleTypeSpec.Versions", "valueType": { - "$id": "67", + "$id": "75", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -854,32 +976,36 @@ }, "values": [ { - "$id": "68", + "$id": "76", "kind": "enumvalue", "name": "2024-07-16-preview", "value": "2024-07-16-preview", "valueType": { - "$ref": "67" + "$ref": "75" }, "enumType": { - "$ref": "66" + "$ref": "74" }, "decorators": [], "isExactName": false }, { - "$id": "69", + "$id": "77", "kind": "enumvalue", "name": "2024-08-16-preview", "value": "2024-08-16-preview", "valueType": { - "$ref": "67" + "$ref": "75" }, "enumType": { - "$ref": "66" + "$ref": "74" }, "decorators": [], - "isExactName": false + "isExactName": false, + "experimental": { + "diagnosticId": "SAMPLE0010", + "dependsOn": [] + } } ], "namespace": "SampleTypeSpec", @@ -892,13 +1018,13 @@ ], "constants": [ { - "$id": "70", + "$id": "78", "kind": "constant", "name": "ThingRequiredLiteralString", "namespace": "SampleTypeSpec", "usage": "Input,Output,Spread,Json", "valueType": { - "$id": "71", + "$id": "79", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -909,13 +1035,13 @@ "isExactName": false }, { - "$id": "72", + "$id": "80", "kind": "constant", "name": "ThingRequiredLiteralInt", "namespace": "SampleTypeSpec", "usage": "Input,Output,Spread,Json", "valueType": { - "$id": "73", + "$id": "81", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -926,13 +1052,13 @@ "isExactName": false }, { - "$id": "74", + "$id": "82", "kind": "constant", "name": "ThingRequiredLiteralFloat", "namespace": "SampleTypeSpec", "usage": "Input,Output,Spread,Json", "valueType": { - "$id": "75", + "$id": "83", "kind": "float32", "name": "float32", "crossLanguageDefinitionId": "TypeSpec.float32", @@ -943,13 +1069,13 @@ "isExactName": false }, { - "$id": "76", + "$id": "84", "kind": "constant", "name": "ThingRequiredLiteralBool", "namespace": "SampleTypeSpec", "usage": "Input,Output,Spread,Json", "valueType": { - "$id": "77", + "$id": "85", "kind": "boolean", "name": "boolean", "crossLanguageDefinitionId": "TypeSpec.boolean", @@ -960,13 +1086,13 @@ "isExactName": false }, { - "$id": "78", + "$id": "86", "kind": "constant", "name": "ThingOptionalLiteralBool", "namespace": "SampleTypeSpec", "usage": "Input,Output,Spread,Json", "valueType": { - "$id": "79", + "$id": "87", "kind": "boolean", "name": "boolean", "crossLanguageDefinitionId": "TypeSpec.boolean", @@ -977,13 +1103,13 @@ "isExactName": false }, { - "$id": "80", + "$id": "88", "kind": "constant", "name": "PetKind", "namespace": "SampleTypeSpec", "usage": "Input,Output,Json", "valueType": { - "$id": "81", + "$id": "89", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -994,13 +1120,13 @@ "isExactName": false }, { - "$id": "82", + "$id": "90", "kind": "constant", "name": "DogKind", "namespace": "SampleTypeSpec", "usage": "Input,Output,Json", "valueType": { - "$id": "83", + "$id": "91", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1011,13 +1137,13 @@ "isExactName": false }, { - "$id": "84", + "$id": "92", "kind": "constant", "name": "TreeSpecies", "namespace": "SampleTypeSpec", "usage": "Input,Output,Json,Xml", "valueType": { - "$id": "85", + "$id": "93", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1028,13 +1154,13 @@ "isExactName": false }, { - "$id": "86", + "$id": "94", "kind": "constant", "name": "GetTreeAsJsonResponseContentType", "namespace": "", "usage": "None", "valueType": { - "$id": "87", + "$id": "95", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1045,13 +1171,13 @@ "isExactName": false }, { - "$id": "88", + "$id": "96", "kind": "constant", "name": "HelloAgainRequestContentType", "namespace": "", "usage": "None", "valueType": { - "$id": "89", + "$id": "97", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1062,13 +1188,13 @@ "isExactName": false }, { - "$id": "90", + "$id": "98", "kind": "constant", "name": "HelloAgainRequestContentType1", "namespace": "", "usage": "None", "valueType": { - "$id": "91", + "$id": "99", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1079,13 +1205,13 @@ "isExactName": false }, { - "$id": "92", + "$id": "100", "kind": "constant", "name": "GetTreeAsJsonResponseContentType1", "namespace": "", "usage": "None", "valueType": { - "$id": "93", + "$id": "101", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1096,13 +1222,13 @@ "isExactName": false }, { - "$id": "94", + "$id": "102", "kind": "constant", "name": "GetTreeAsJsonResponseContentType2", "namespace": "", "usage": "None", "valueType": { - "$id": "95", + "$id": "103", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1113,13 +1239,13 @@ "isExactName": false }, { - "$id": "96", + "$id": "104", "kind": "constant", "name": "GetTreeAsJsonResponseContentType3", "namespace": "", "usage": "None", "valueType": { - "$id": "97", + "$id": "105", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1130,13 +1256,13 @@ "isExactName": false }, { - "$id": "98", + "$id": "106", "kind": "constant", "name": "GetTreeAsJsonResponseContentType4", "namespace": "", "usage": "None", "valueType": { - "$id": "99", + "$id": "107", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1147,13 +1273,13 @@ "isExactName": false }, { - "$id": "100", + "$id": "108", "kind": "constant", "name": "GetTreeAsJsonResponseContentType5", "namespace": "", "usage": "None", "valueType": { - "$id": "101", + "$id": "109", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1164,13 +1290,13 @@ "isExactName": false }, { - "$id": "102", + "$id": "110", "kind": "constant", "name": "GetTreeAsJsonResponseContentType6", "namespace": "", "usage": "None", "valueType": { - "$id": "103", + "$id": "111", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1181,13 +1307,13 @@ "isExactName": false }, { - "$id": "104", + "$id": "112", "kind": "constant", "name": "HelloLiteralRequestP1", "namespace": "", "usage": "None", "valueType": { - "$id": "105", + "$id": "113", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1198,13 +1324,13 @@ "isExactName": false }, { - "$id": "106", + "$id": "114", "kind": "constant", "name": "HelloLiteralRequestP11", "namespace": "", "usage": "None", "valueType": { - "$id": "107", + "$id": "115", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1215,13 +1341,13 @@ "isExactName": false }, { - "$id": "108", + "$id": "116", "kind": "constant", "name": "ThingRequiredLiteralInt1", "namespace": "", "usage": "None", "valueType": { - "$id": "109", + "$id": "117", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -1232,13 +1358,13 @@ "isExactName": false }, { - "$id": "110", + "$id": "118", "kind": "constant", "name": "ThingRequiredLiteralInt2", "namespace": "", "usage": "None", "valueType": { - "$id": "111", + "$id": "119", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -1249,13 +1375,13 @@ "isExactName": false }, { - "$id": "112", + "$id": "120", "kind": "constant", "name": "ThingOptionalLiteralBool1", "namespace": "", "usage": "None", "valueType": { - "$id": "113", + "$id": "121", "kind": "boolean", "name": "boolean", "crossLanguageDefinitionId": "TypeSpec.boolean", @@ -1266,13 +1392,13 @@ "isExactName": false }, { - "$id": "114", + "$id": "122", "kind": "constant", "name": "ThingOptionalLiteralBool2", "namespace": "", "usage": "None", "valueType": { - "$id": "115", + "$id": "123", "kind": "boolean", "name": "boolean", "crossLanguageDefinitionId": "TypeSpec.boolean", @@ -1283,13 +1409,13 @@ "isExactName": false }, { - "$id": "116", + "$id": "124", "kind": "constant", "name": "GetTreeAsJsonResponseContentType7", "namespace": "", "usage": "None", "valueType": { - "$id": "117", + "$id": "125", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1300,13 +1426,13 @@ "isExactName": false }, { - "$id": "118", + "$id": "126", "kind": "constant", "name": "GetTreeAsJsonResponseContentType8", "namespace": "", "usage": "None", "valueType": { - "$id": "119", + "$id": "127", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1317,13 +1443,13 @@ "isExactName": false }, { - "$id": "120", + "$id": "128", "kind": "constant", "name": "GetTreeAsJsonResponseContentType9", "namespace": "", "usage": "None", "valueType": { - "$id": "121", + "$id": "129", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1334,13 +1460,13 @@ "isExactName": false }, { - "$id": "122", + "$id": "130", "kind": "constant", "name": "GetTreeAsJsonResponseContentType10", "namespace": "", "usage": "None", "valueType": { - "$id": "123", + "$id": "131", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1351,13 +1477,13 @@ "isExactName": false }, { - "$id": "124", + "$id": "132", "kind": "constant", "name": "GetTreeAsJsonResponseContentType11", "namespace": "", "usage": "None", "valueType": { - "$id": "125", + "$id": "133", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1368,13 +1494,13 @@ "isExactName": false }, { - "$id": "126", + "$id": "134", "kind": "constant", "name": "AnonymousBodyRequestRequiredQueryParam", "namespace": "", "usage": "None", "valueType": { - "$id": "127", + "$id": "135", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1385,13 +1511,13 @@ "isExactName": false }, { - "$id": "128", + "$id": "136", "kind": "constant", "name": "AnonymousBodyRequestRequiredQueryParam1", "namespace": "", "usage": "None", "valueType": { - "$id": "129", + "$id": "137", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1402,13 +1528,13 @@ "isExactName": false }, { - "$id": "130", + "$id": "138", "kind": "constant", "name": "AnonymousBodyRequestRequiredHeader", "namespace": "", "usage": "None", "valueType": { - "$id": "131", + "$id": "139", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1419,13 +1545,13 @@ "isExactName": false }, { - "$id": "132", + "$id": "140", "kind": "constant", "name": "AnonymousBodyRequestRequiredHeader1", "namespace": "", "usage": "None", "valueType": { - "$id": "133", + "$id": "141", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1436,13 +1562,13 @@ "isExactName": false }, { - "$id": "134", + "$id": "142", "kind": "constant", "name": "GetTreeAsJsonResponseContentType12", "namespace": "", "usage": "None", "valueType": { - "$id": "135", + "$id": "143", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1453,13 +1579,13 @@ "isExactName": false }, { - "$id": "136", + "$id": "144", "kind": "constant", "name": "GetTreeAsJsonResponseContentType13", "namespace": "", "usage": "None", "valueType": { - "$id": "137", + "$id": "145", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1470,13 +1596,13 @@ "isExactName": false }, { - "$id": "138", + "$id": "146", "kind": "constant", "name": "ThingRequiredLiteralString1", "namespace": "", "usage": "None", "valueType": { - "$id": "139", + "$id": "147", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -1487,13 +1613,13 @@ "isExactName": false }, { - "$id": "140", + "$id": "148", "kind": "constant", "name": "ThingRequiredLiteralInt3", "namespace": "", "usage": "None", "valueType": { - "$id": "141", + "$id": "149", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -1504,13 +1630,13 @@ "isExactName": false }, { - "$id": "142", + "$id": "150", "kind": "constant", "name": "ThingRequiredLiteralFloat1", "namespace": "", "usage": "None", "valueType": { - "$id": "143", + "$id": "151", "kind": "float32", "name": "float32", "crossLanguageDefinitionId": "TypeSpec.float32", @@ -1521,13 +1647,13 @@ "isExactName": false }, { - "$id": "144", + "$id": "152", "kind": "constant", "name": "ThingRequiredLiteralBool1", "namespace": "", "usage": "None", "valueType": { - "$id": "145", + "$id": "153", "kind": "boolean", "name": "boolean", "crossLanguageDefinitionId": "TypeSpec.boolean", @@ -1538,13 +1664,13 @@ "isExactName": false }, { - "$id": "146", + "$id": "154", "kind": "constant", "name": "ThingOptionalLiteralBool3", "namespace": "", "usage": "None", "valueType": { - "$id": "147", + "$id": "155", "kind": "boolean", "name": "boolean", "crossLanguageDefinitionId": "TypeSpec.boolean", @@ -1554,78 +1680,10 @@ "decorators": [], "isExactName": false }, - { - "$id": "148", - "kind": "constant", - "name": "GetTreeAsJsonResponseContentType14", - "namespace": "", - "usage": "None", - "valueType": { - "$id": "149", - "kind": "string", - "name": "string", - "crossLanguageDefinitionId": "TypeSpec.string", - "decorators": [] - }, - "value": "application/json", - "decorators": [], - "isExactName": false - }, - { - "$id": "150", - "kind": "constant", - "name": "GetTreeAsJsonResponseContentType15", - "namespace": "", - "usage": "None", - "valueType": { - "$id": "151", - "kind": "string", - "name": "string", - "crossLanguageDefinitionId": "TypeSpec.string", - "decorators": [] - }, - "value": "application/json", - "decorators": [], - "isExactName": false - }, - { - "$id": "152", - "kind": "constant", - "name": "GetTreeAsJsonResponseContentType16", - "namespace": "", - "usage": "None", - "valueType": { - "$id": "153", - "kind": "string", - "name": "string", - "crossLanguageDefinitionId": "TypeSpec.string", - "decorators": [] - }, - "value": "application/json", - "decorators": [], - "isExactName": false - }, - { - "$id": "154", - "kind": "constant", - "name": "GetTreeAsJsonResponseContentType17", - "namespace": "", - "usage": "None", - "valueType": { - "$id": "155", - "kind": "string", - "name": "string", - "crossLanguageDefinitionId": "TypeSpec.string", - "decorators": [] - }, - "value": "application/json", - "decorators": [], - "isExactName": false - }, { "$id": "156", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType18", + "name": "GetTreeAsJsonResponseContentType14", "namespace": "", "usage": "None", "valueType": { @@ -1642,7 +1700,7 @@ { "$id": "158", "kind": "constant", - "name": "HelloAgainRequestContentType2", + "name": "GetTreeAsJsonResponseContentType15", "namespace": "", "usage": "None", "valueType": { @@ -1652,14 +1710,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "text/plain", + "value": "application/json", "decorators": [], "isExactName": false }, { "$id": "160", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType19", + "name": "GetTreeAsJsonResponseContentType16", "namespace": "", "usage": "None", "valueType": { @@ -1676,7 +1734,7 @@ { "$id": "162", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType20", + "name": "GetTreeAsJsonResponseContentType17", "namespace": "", "usage": "None", "valueType": { @@ -1693,7 +1751,7 @@ { "$id": "164", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType21", + "name": "GetTreeAsJsonResponseContentType18", "namespace": "", "usage": "None", "valueType": { @@ -1710,7 +1768,7 @@ { "$id": "166", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType22", + "name": "HelloAgainRequestContentType2", "namespace": "", "usage": "None", "valueType": { @@ -1720,14 +1778,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/json", + "value": "text/plain", "decorators": [], "isExactName": false }, { "$id": "168", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType23", + "name": "GetTreeAsJsonResponseContentType19", "namespace": "", "usage": "None", "valueType": { @@ -1744,7 +1802,7 @@ { "$id": "170", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType24", + "name": "GetTreeAsJsonResponseContentType20", "namespace": "", "usage": "None", "valueType": { @@ -1761,7 +1819,7 @@ { "$id": "172", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType25", + "name": "GetTreeAsJsonResponseContentType21", "namespace": "", "usage": "None", "valueType": { @@ -1778,7 +1836,7 @@ { "$id": "174", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType26", + "name": "GetTreeAsJsonResponseContentType22", "namespace": "", "usage": "None", "valueType": { @@ -1795,7 +1853,7 @@ { "$id": "176", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType27", + "name": "GetTreeAsJsonResponseContentType23", "namespace": "", "usage": "None", "valueType": { @@ -1812,7 +1870,7 @@ { "$id": "178", "kind": "constant", - "name": "GetXmlAdvancedModelResponseContentType", + "name": "GetTreeAsJsonResponseContentType24", "namespace": "", "usage": "None", "valueType": { @@ -1822,14 +1880,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/xml", + "value": "application/json", "decorators": [], "isExactName": false }, { "$id": "180", "kind": "constant", - "name": "GetXmlAdvancedModelResponseContentType1", + "name": "GetTreeAsJsonResponseContentType25", "namespace": "", "usage": "None", "valueType": { @@ -1839,14 +1897,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/xml", + "value": "application/json", "decorators": [], "isExactName": false }, { "$id": "182", "kind": "constant", - "name": "GetXmlAdvancedModelResponseContentType2", + "name": "GetTreeAsJsonResponseContentType26", "namespace": "", "usage": "None", "valueType": { @@ -1856,14 +1914,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/xml", + "value": "application/json", "decorators": [], "isExactName": false }, { "$id": "184", "kind": "constant", - "name": "GetXmlAdvancedModelResponseContentType3", + "name": "GetTreeAsJsonResponseContentType27", "namespace": "", "usage": "None", "valueType": { @@ -1873,14 +1931,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/xml", + "value": "application/json", "decorators": [], "isExactName": false }, { "$id": "186", "kind": "constant", - "name": "GetXmlAdvancedModelResponseContentType4", + "name": "GetXmlAdvancedModelResponseContentType", "namespace": "", "usage": "None", "valueType": { @@ -1897,7 +1955,7 @@ { "$id": "188", "kind": "constant", - "name": "GetXmlAdvancedModelResponseContentType5", + "name": "GetXmlAdvancedModelResponseContentType1", "namespace": "", "usage": "None", "valueType": { @@ -1914,7 +1972,7 @@ { "$id": "190", "kind": "constant", - "name": "UploadCatRequestContentType", + "name": "GetXmlAdvancedModelResponseContentType2", "namespace": "", "usage": "None", "valueType": { @@ -1924,14 +1982,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "multipart/form-data", + "value": "application/xml", "decorators": [], "isExactName": false }, { "$id": "192", "kind": "constant", - "name": "UploadCatRequestContentType1", + "name": "GetXmlAdvancedModelResponseContentType3", "namespace": "", "usage": "None", "valueType": { @@ -1941,14 +1999,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "multipart/form-data", + "value": "application/xml", "decorators": [], "isExactName": false }, { "$id": "194", "kind": "constant", - "name": "SendJsonLinesRequestContentType", + "name": "GetXmlAdvancedModelResponseContentType4", "namespace": "", "usage": "None", "valueType": { @@ -1958,15 +2016,15 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/jsonl", + "value": "application/xml", "decorators": [], "isExactName": false }, { "$id": "196", "kind": "constant", - "name": "JsonlStreamStreamingItemContentType", - "namespace": "TypeSpec.Http.Streams", + "name": "GetXmlAdvancedModelResponseContentType5", + "namespace": "", "usage": "None", "valueType": { "$id": "197", @@ -1975,14 +2033,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/jsonl", + "value": "application/xml", "decorators": [], "isExactName": false }, { "$id": "198", "kind": "constant", - "name": "SendJsonLinesRequestContentType1", + "name": "UploadCatRequestContentType", "namespace": "", "usage": "None", "valueType": { @@ -1992,14 +2050,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/jsonl", + "value": "multipart/form-data", "decorators": [], "isExactName": false }, { "$id": "200", "kind": "constant", - "name": "SendJsonLinesRequestContentType2", + "name": "UploadCatRequestContentType1", "namespace": "", "usage": "None", "valueType": { @@ -2009,14 +2067,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/jsonl", + "value": "multipart/form-data", "decorators": [], "isExactName": false }, { "$id": "202", "kind": "constant", - "name": "ReceiveSseResponseContentType", + "name": "SendJsonLinesRequestContentType", "namespace": "", "usage": "None", "valueType": { @@ -2026,15 +2084,15 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "text/event-stream", + "value": "application/jsonl", "decorators": [], "isExactName": false }, { "$id": "204", "kind": "constant", - "name": "ReceiveSse", - "namespace": "", + "name": "JsonlStreamStreamingItemContentType", + "namespace": "TypeSpec.Http.Streams", "usage": "None", "valueType": { "$id": "205", @@ -2043,14 +2101,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "[DONE]", + "value": "application/jsonl", "decorators": [], "isExactName": false }, { "$id": "206", "kind": "constant", - "name": "ReceiveSseResponseContentType1", + "name": "SendJsonLinesRequestContentType1", "namespace": "", "usage": "None", "valueType": { @@ -2060,14 +2118,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "text/event-stream", + "value": "application/jsonl", "decorators": [], "isExactName": false }, { "$id": "208", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType28", + "name": "SendJsonLinesRequestContentType2", "namespace": "", "usage": "None", "valueType": { @@ -2077,14 +2135,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/json", + "value": "application/jsonl", "decorators": [], "isExactName": false }, { "$id": "210", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType29", + "name": "ReceiveSseResponseContentType", "namespace": "", "usage": "None", "valueType": { @@ -2094,14 +2152,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/json", + "value": "text/event-stream", "decorators": [], "isExactName": false }, { "$id": "212", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType30", + "name": "ReceiveSse", "namespace": "", "usage": "None", "valueType": { @@ -2111,14 +2169,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/json", + "value": "[DONE]", "decorators": [], "isExactName": false }, { "$id": "214", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType31", + "name": "ReceiveSseResponseContentType1", "namespace": "", "usage": "None", "valueType": { @@ -2128,14 +2186,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/json", + "value": "text/event-stream", "decorators": [], "isExactName": false }, { "$id": "216", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType32", + "name": "SendJsonLinesRequestContentType3", "namespace": "", "usage": "None", "valueType": { @@ -2145,14 +2203,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/json", + "value": "application/jsonl", "decorators": [], "isExactName": false }, { "$id": "218", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType33", + "name": "SendJsonLinesRequestContentType4", "namespace": "", "usage": "None", "valueType": { @@ -2162,14 +2220,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/json", + "value": "application/jsonl", "decorators": [], "isExactName": false }, { "$id": "220", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType34", + "name": "GetTreeAsJsonResponseContentType28", "namespace": "", "usage": "None", "valueType": { @@ -2186,7 +2244,7 @@ { "$id": "222", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType35", + "name": "GetTreeAsJsonResponseContentType29", "namespace": "", "usage": "None", "valueType": { @@ -2203,7 +2261,7 @@ { "$id": "224", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType36", + "name": "GetTreeAsJsonResponseContentType30", "namespace": "", "usage": "None", "valueType": { @@ -2220,7 +2278,7 @@ { "$id": "226", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType37", + "name": "GetTreeAsJsonResponseContentType31", "namespace": "", "usage": "None", "valueType": { @@ -2237,7 +2295,7 @@ { "$id": "228", "kind": "constant", - "name": "GetXmlAdvancedModelResponseContentType6", + "name": "GetTreeAsJsonResponseContentType32", "namespace": "", "usage": "None", "valueType": { @@ -2247,14 +2305,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/xml", + "value": "application/json", "decorators": [], "isExactName": false }, { "$id": "230", "kind": "constant", - "name": "GetXmlAdvancedModelResponseContentType7", + "name": "GetTreeAsJsonResponseContentType33", "namespace": "", "usage": "None", "valueType": { @@ -2264,14 +2322,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/xml", + "value": "application/json", "decorators": [], "isExactName": false }, { "$id": "232", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType38", + "name": "GetTreeAsJsonResponseContentType34", "namespace": "", "usage": "None", "valueType": { @@ -2288,7 +2346,7 @@ { "$id": "234", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType39", + "name": "GetTreeAsJsonResponseContentType35", "namespace": "", "usage": "None", "valueType": { @@ -2305,7 +2363,7 @@ { "$id": "236", "kind": "constant", - "name": "GetXmlAdvancedModelResponseContentType8", + "name": "GetTreeAsJsonResponseContentType36", "namespace": "", "usage": "None", "valueType": { @@ -2315,14 +2373,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/xml", + "value": "application/json", "decorators": [], "isExactName": false }, { "$id": "238", "kind": "constant", - "name": "GetXmlAdvancedModelResponseContentType9", + "name": "GetTreeAsJsonResponseContentType37", "namespace": "", "usage": "None", "valueType": { @@ -2332,14 +2390,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/xml", + "value": "application/json", "decorators": [], "isExactName": false }, { "$id": "240", "kind": "constant", - "name": "GetXmlAdvancedModelResponseContentType10", + "name": "GetTreeAsJsonResponseContentType38", "namespace": "", "usage": "None", "valueType": { @@ -2349,14 +2407,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/xml", + "value": "application/json", "decorators": [], "isExactName": false }, { "$id": "242", "kind": "constant", - "name": "GetXmlAdvancedModelResponseContentType11", + "name": "GetTreeAsJsonResponseContentType39", "namespace": "", "usage": "None", "valueType": { @@ -2366,14 +2424,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/xml", + "value": "application/json", "decorators": [], "isExactName": false }, { "$id": "244", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType40", + "name": "GetXmlAdvancedModelResponseContentType6", "namespace": "", "usage": "None", "valueType": { @@ -2383,14 +2441,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/json", + "value": "application/xml", "decorators": [], "isExactName": false }, { "$id": "246", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType41", + "name": "GetXmlAdvancedModelResponseContentType7", "namespace": "", "usage": "None", "valueType": { @@ -2400,14 +2458,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/json", + "value": "application/xml", "decorators": [], "isExactName": false }, { "$id": "248", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType42", + "name": "GetTreeAsJsonResponseContentType40", "namespace": "", "usage": "None", "valueType": { @@ -2424,7 +2482,7 @@ { "$id": "250", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType43", + "name": "GetTreeAsJsonResponseContentType41", "namespace": "", "usage": "None", "valueType": { @@ -2441,7 +2499,7 @@ { "$id": "252", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType44", + "name": "GetXmlAdvancedModelResponseContentType8", "namespace": "", "usage": "None", "valueType": { @@ -2451,14 +2509,14 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, - "value": "application/json", + "value": "application/xml", "decorators": [], "isExactName": false }, { "$id": "254", "kind": "constant", - "name": "GetTreeAsJsonResponseContentType45", + "name": "GetXmlAdvancedModelResponseContentType9", "namespace": "", "usage": "None", "valueType": { @@ -2468,6 +2526,142 @@ "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, + "value": "application/xml", + "decorators": [], + "isExactName": false + }, + { + "$id": "256", + "kind": "constant", + "name": "GetXmlAdvancedModelResponseContentType10", + "namespace": "", + "usage": "None", + "valueType": { + "$id": "257", + "kind": "string", + "name": "string", + "crossLanguageDefinitionId": "TypeSpec.string", + "decorators": [] + }, + "value": "application/xml", + "decorators": [], + "isExactName": false + }, + { + "$id": "258", + "kind": "constant", + "name": "GetXmlAdvancedModelResponseContentType11", + "namespace": "", + "usage": "None", + "valueType": { + "$id": "259", + "kind": "string", + "name": "string", + "crossLanguageDefinitionId": "TypeSpec.string", + "decorators": [] + }, + "value": "application/xml", + "decorators": [], + "isExactName": false + }, + { + "$id": "260", + "kind": "constant", + "name": "GetTreeAsJsonResponseContentType42", + "namespace": "", + "usage": "None", + "valueType": { + "$id": "261", + "kind": "string", + "name": "string", + "crossLanguageDefinitionId": "TypeSpec.string", + "decorators": [] + }, + "value": "application/json", + "decorators": [], + "isExactName": false + }, + { + "$id": "262", + "kind": "constant", + "name": "GetTreeAsJsonResponseContentType43", + "namespace": "", + "usage": "None", + "valueType": { + "$id": "263", + "kind": "string", + "name": "string", + "crossLanguageDefinitionId": "TypeSpec.string", + "decorators": [] + }, + "value": "application/json", + "decorators": [], + "isExactName": false + }, + { + "$id": "264", + "kind": "constant", + "name": "GetTreeAsJsonResponseContentType44", + "namespace": "", + "usage": "None", + "valueType": { + "$id": "265", + "kind": "string", + "name": "string", + "crossLanguageDefinitionId": "TypeSpec.string", + "decorators": [] + }, + "value": "application/json", + "decorators": [], + "isExactName": false + }, + { + "$id": "266", + "kind": "constant", + "name": "GetTreeAsJsonResponseContentType45", + "namespace": "", + "usage": "None", + "valueType": { + "$id": "267", + "kind": "string", + "name": "string", + "crossLanguageDefinitionId": "TypeSpec.string", + "decorators": [] + }, + "value": "application/json", + "decorators": [], + "isExactName": false + }, + { + "$id": "268", + "kind": "constant", + "name": "GetTreeAsJsonResponseContentType46", + "namespace": "", + "usage": "None", + "valueType": { + "$id": "269", + "kind": "string", + "name": "string", + "crossLanguageDefinitionId": "TypeSpec.string", + "decorators": [] + }, + "value": "application/json", + "decorators": [], + "isExactName": false + }, + { + "$id": "270", + "kind": "constant", + "name": "GetTreeAsJsonResponseContentType47", + "namespace": "", + "usage": "None", + "valueType": { + "$id": "271", + "kind": "string", + "name": "string", + "crossLanguageDefinitionId": "TypeSpec.string", + "decorators": [] + }, "value": "application/json", "decorators": [], "isExactName": false @@ -2475,7 +2669,7 @@ ], "models": [ { - "$id": "256", + "$id": "272", "kind": "model", "name": "Thing", "apiVersions": [ @@ -2495,7 +2689,7 @@ "isExactName": false, "properties": [ { - "$id": "257", + "$id": "273", "kind": "property", "name": "name", "apiVersions": [ @@ -2505,7 +2699,7 @@ "serializedName": "name", "doc": "name of the Thing", "type": { - "$id": "258", + "$id": "274", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -2526,7 +2720,7 @@ "isExactName": false }, { - "$id": "259", + "$id": "275", "kind": "property", "name": "requiredUnion", "apiVersions": [ @@ -2536,23 +2730,23 @@ "serializedName": "requiredUnion", "doc": "required Union", "type": { - "$id": "260", + "$id": "276", "kind": "union", "name": "ThingRequiredUnion", "variantTypes": [ { - "$id": "261", + "$id": "277", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, { - "$id": "262", + "$id": "278", "kind": "array", "name": "Array", "valueType": { - "$id": "263", + "$id": "279", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -2562,7 +2756,7 @@ "decorators": [] }, { - "$id": "264", + "$id": "280", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -2588,7 +2782,7 @@ "isExactName": false }, { - "$id": "265", + "$id": "281", "kind": "property", "name": "requiredLiteralString", "apiVersions": [ @@ -2598,7 +2792,7 @@ "serializedName": "requiredLiteralString", "doc": "required literal string", "type": { - "$ref": "70" + "$ref": "78" }, "optional": false, "readOnly": false, @@ -2615,7 +2809,7 @@ "isExactName": false }, { - "$id": "266", + "$id": "282", "kind": "property", "name": "requiredNullableString", "apiVersions": [ @@ -2625,10 +2819,10 @@ "serializedName": "requiredNullableString", "doc": "required nullable string", "type": { - "$id": "267", + "$id": "283", "kind": "nullable", "type": { - "$id": "268", + "$id": "284", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -2651,7 +2845,7 @@ "isExactName": false }, { - "$id": "269", + "$id": "285", "kind": "property", "name": "optionalNullableString", "apiVersions": [ @@ -2661,10 +2855,10 @@ "serializedName": "optionalNullableString", "doc": "required optional string", "type": { - "$id": "270", + "$id": "286", "kind": "nullable", "type": { - "$id": "271", + "$id": "287", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -2687,7 +2881,7 @@ "isExactName": false }, { - "$id": "272", + "$id": "288", "kind": "property", "name": "requiredLiteralInt", "apiVersions": [ @@ -2697,7 +2891,7 @@ "serializedName": "requiredLiteralInt", "doc": "required literal int", "type": { - "$ref": "72" + "$ref": "80" }, "optional": false, "readOnly": false, @@ -2714,7 +2908,7 @@ "isExactName": false }, { - "$id": "273", + "$id": "289", "kind": "property", "name": "requiredLiteralFloat", "apiVersions": [ @@ -2724,7 +2918,7 @@ "serializedName": "requiredLiteralFloat", "doc": "required literal float", "type": { - "$ref": "74" + "$ref": "82" }, "optional": false, "readOnly": false, @@ -2741,7 +2935,7 @@ "isExactName": false }, { - "$id": "274", + "$id": "290", "kind": "property", "name": "requiredLiteralBool", "apiVersions": [ @@ -2751,7 +2945,7 @@ "serializedName": "requiredLiteralBool", "doc": "required literal bool", "type": { - "$ref": "76" + "$ref": "84" }, "optional": false, "readOnly": false, @@ -2768,7 +2962,7 @@ "isExactName": false }, { - "$id": "275", + "$id": "291", "kind": "property", "name": "optionalLiteralString", "apiVersions": [ @@ -2795,7 +2989,7 @@ "isExactName": false }, { - "$id": "276", + "$id": "292", "kind": "property", "name": "requiredNullableLiteralString", "apiVersions": [ @@ -2805,7 +2999,7 @@ "serializedName": "requiredNullableLiteralString", "doc": "required nullable literal string", "type": { - "$id": "277", + "$id": "293", "kind": "nullable", "type": { "$ref": "5" @@ -2827,7 +3021,7 @@ "isExactName": false }, { - "$id": "278", + "$id": "294", "kind": "property", "name": "optionalLiteralInt", "apiVersions": [ @@ -2854,7 +3048,7 @@ "isExactName": false }, { - "$id": "279", + "$id": "295", "kind": "property", "name": "optionalLiteralFloat", "apiVersions": [ @@ -2881,7 +3075,7 @@ "isExactName": false }, { - "$id": "280", + "$id": "296", "kind": "property", "name": "optionalLiteralBool", "apiVersions": [ @@ -2891,7 +3085,7 @@ "serializedName": "optionalLiteralBool", "doc": "optional literal bool", "type": { - "$ref": "78" + "$ref": "86" }, "optional": true, "readOnly": false, @@ -2908,7 +3102,7 @@ "isExactName": false }, { - "$id": "281", + "$id": "297", "kind": "property", "name": "requiredBadDescription", "apiVersions": [ @@ -2918,7 +3112,7 @@ "serializedName": "requiredBadDescription", "doc": "description with xml <|endoftext|>", "type": { - "$id": "282", + "$id": "298", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -2939,7 +3133,7 @@ "isExactName": false }, { - "$id": "283", + "$id": "299", "kind": "property", "name": "optionalNullableList", "apiVersions": [ @@ -2949,14 +3143,14 @@ "serializedName": "optionalNullableList", "doc": "optional nullable collection", "type": { - "$id": "284", + "$id": "300", "kind": "nullable", "type": { - "$id": "285", + "$id": "301", "kind": "array", "name": "Array1", "valueType": { - "$id": "286", + "$id": "302", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -2982,7 +3176,7 @@ "isExactName": false }, { - "$id": "287", + "$id": "303", "kind": "property", "name": "requiredNullableList", "apiVersions": [ @@ -2992,10 +3186,10 @@ "serializedName": "requiredNullableList", "doc": "required nullable collection", "type": { - "$id": "288", + "$id": "304", "kind": "nullable", "type": { - "$ref": "285" + "$ref": "301" }, "namespace": "SampleTypeSpec" }, @@ -3014,7 +3208,7 @@ "isExactName": false }, { - "$id": "289", + "$id": "305", "kind": "property", "name": "propertyWithSpecialDocs", "apiVersions": [ @@ -3024,7 +3218,7 @@ "serializedName": "propertyWithSpecialDocs", "doc": "This tests:\n- Simple bullet point. This bullet point is going to be very long to test how text wrapping is handled in bullet points within documentation comments. It should properly indent the wrapped lines.\n- Another bullet point with **bold text**. This bullet point is also intentionally long to see how the formatting is preserved when the text wraps onto multiple lines in the generated documentation.\n- Third bullet point with *italic text*. Similar to the previous points, this one is extended to ensure that the wrapping and formatting are correctly applied in the output.\n- Complex bullet point with **bold** and *italic* combined. This bullet point combines both bold and italic formatting and is long enough to test the wrapping behavior in such cases.\n- **Bold bullet point**: A bullet point that is entirely bolded. This point is also made lengthy to observe how the bold formatting is maintained across wrapped lines.\n- *Italic bullet point*: A bullet point that is entirely italicized. This final point is extended to verify that italic formatting is correctly applied even when the text spans multiple lines.", "type": { - "$id": "290", + "$id": "306", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -3047,7 +3241,7 @@ ] }, { - "$id": "291", + "$id": "307", "kind": "model", "name": "RoundTripModel", "apiVersions": [ @@ -3067,7 +3261,7 @@ "isExactName": false, "properties": [ { - "$id": "292", + "$id": "308", "kind": "property", "name": "requiredString", "apiVersions": [ @@ -3077,7 +3271,7 @@ "serializedName": "requiredString", "doc": "Required string, illustrating a reference type property.", "type": { - "$id": "293", + "$id": "309", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -3098,7 +3292,7 @@ "isExactName": false }, { - "$id": "294", + "$id": "310", "kind": "property", "name": "requiredInt", "apiVersions": [ @@ -3108,7 +3302,7 @@ "serializedName": "requiredInt", "doc": "Required int, illustrating a value type property.", "type": { - "$id": "295", + "$id": "311", "kind": "int32", "name": "int32", "encode": "string", @@ -3130,7 +3324,7 @@ "isExactName": false }, { - "$id": "296", + "$id": "312", "kind": "property", "name": "requiredCollection", "apiVersions": [ @@ -3140,7 +3334,7 @@ "serializedName": "requiredCollection", "doc": "Required collection of enums", "type": { - "$id": "297", + "$id": "313", "kind": "array", "name": "ArrayStringFixedEnum", "valueType": { @@ -3164,7 +3358,7 @@ "isExactName": false }, { - "$id": "298", + "$id": "314", "kind": "property", "name": "requiredDictionary", "apiVersions": [ @@ -3174,10 +3368,10 @@ "serializedName": "requiredDictionary", "doc": "Required dictionary of enums", "type": { - "$id": "299", + "$id": "315", "kind": "dict", "keyType": { - "$id": "300", + "$id": "316", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -3203,7 +3397,7 @@ "isExactName": false }, { - "$id": "301", + "$id": "317", "kind": "property", "name": "requiredModel", "apiVersions": [ @@ -3213,7 +3407,7 @@ "serializedName": "requiredModel", "doc": "Required model", "type": { - "$ref": "256" + "$ref": "272" }, "optional": false, "readOnly": false, @@ -3230,7 +3424,7 @@ "isExactName": false }, { - "$id": "302", + "$id": "318", "kind": "property", "name": "intExtensibleEnum", "apiVersions": [ @@ -3257,7 +3451,7 @@ "isExactName": false }, { - "$id": "303", + "$id": "319", "kind": "property", "name": "intExtensibleEnumCollection", "apiVersions": [ @@ -3267,7 +3461,7 @@ "serializedName": "intExtensibleEnumCollection", "doc": "this is a collection of int based extensible enum", "type": { - "$id": "304", + "$id": "320", "kind": "array", "name": "ArrayIntExtensibleEnum", "valueType": { @@ -3291,7 +3485,7 @@ "isExactName": false }, { - "$id": "305", + "$id": "321", "kind": "property", "name": "floatExtensibleEnum", "apiVersions": [ @@ -3318,7 +3512,7 @@ "isExactName": false }, { - "$id": "306", + "$id": "322", "kind": "property", "name": "floatExtensibleEnumWithIntValue", "apiVersions": [ @@ -3345,7 +3539,7 @@ "isExactName": false }, { - "$id": "307", + "$id": "323", "kind": "property", "name": "floatExtensibleEnumCollection", "apiVersions": [ @@ -3355,7 +3549,7 @@ "serializedName": "floatExtensibleEnumCollection", "doc": "this is a collection of float based extensible enum", "type": { - "$id": "308", + "$id": "324", "kind": "array", "name": "ArrayFloatExtensibleEnum", "valueType": { @@ -3379,7 +3573,7 @@ "isExactName": false }, { - "$id": "309", + "$id": "325", "kind": "property", "name": "floatFixedEnum", "apiVersions": [ @@ -3406,7 +3600,7 @@ "isExactName": false }, { - "$id": "310", + "$id": "326", "kind": "property", "name": "floatFixedEnumWithIntValue", "apiVersions": [ @@ -3433,7 +3627,7 @@ "isExactName": false }, { - "$id": "311", + "$id": "327", "kind": "property", "name": "floatFixedEnumCollection", "apiVersions": [ @@ -3443,7 +3637,7 @@ "serializedName": "floatFixedEnumCollection", "doc": "this is a collection of float based fixed enum", "type": { - "$id": "312", + "$id": "328", "kind": "array", "name": "ArrayFloatFixedEnum", "valueType": { @@ -3467,7 +3661,7 @@ "isExactName": false }, { - "$id": "313", + "$id": "329", "kind": "property", "name": "intFixedEnum", "apiVersions": [ @@ -3494,7 +3688,7 @@ "isExactName": false }, { - "$id": "314", + "$id": "330", "kind": "property", "name": "intFixedEnumCollection", "apiVersions": [ @@ -3504,7 +3698,7 @@ "serializedName": "intFixedEnumCollection", "doc": "this is a collection of int based fixed enum", "type": { - "$id": "315", + "$id": "331", "kind": "array", "name": "ArrayIntFixedEnum", "valueType": { @@ -3528,7 +3722,7 @@ "isExactName": false }, { - "$id": "316", + "$id": "332", "kind": "property", "name": "stringFixedEnum", "apiVersions": [ @@ -3555,7 +3749,7 @@ "isExactName": false }, { - "$id": "317", + "$id": "333", "kind": "property", "name": "requiredUnknown", "apiVersions": [ @@ -3565,7 +3759,7 @@ "serializedName": "requiredUnknown", "doc": "required unknown", "type": { - "$id": "318", + "$id": "334", "kind": "unknown", "name": "unknown", "crossLanguageDefinitionId": "", @@ -3586,7 +3780,7 @@ "isExactName": false }, { - "$id": "319", + "$id": "335", "kind": "property", "name": "optionalUnknown", "apiVersions": [ @@ -3596,7 +3790,7 @@ "serializedName": "optionalUnknown", "doc": "optional unknown", "type": { - "$id": "320", + "$id": "336", "kind": "unknown", "name": "unknown", "crossLanguageDefinitionId": "", @@ -3617,7 +3811,7 @@ "isExactName": false }, { - "$id": "321", + "$id": "337", "kind": "property", "name": "requiredRecordUnknown", "apiVersions": [ @@ -3627,17 +3821,17 @@ "serializedName": "requiredRecordUnknown", "doc": "required record of unknown", "type": { - "$id": "322", + "$id": "338", "kind": "dict", "keyType": { - "$id": "323", + "$id": "339", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, "valueType": { - "$id": "324", + "$id": "340", "kind": "unknown", "name": "unknown", "crossLanguageDefinitionId": "", @@ -3660,7 +3854,7 @@ "isExactName": false }, { - "$id": "325", + "$id": "341", "kind": "property", "name": "optionalRecordUnknown", "apiVersions": [ @@ -3670,7 +3864,7 @@ "serializedName": "optionalRecordUnknown", "doc": "optional record of unknown", "type": { - "$ref": "322" + "$ref": "338" }, "optional": true, "readOnly": false, @@ -3687,7 +3881,7 @@ "isExactName": false }, { - "$id": "326", + "$id": "342", "kind": "property", "name": "readOnlyRequiredRecordUnknown", "apiVersions": [ @@ -3697,7 +3891,7 @@ "serializedName": "readOnlyRequiredRecordUnknown", "doc": "required readonly record of unknown", "type": { - "$ref": "322" + "$ref": "338" }, "optional": false, "readOnly": true, @@ -3714,7 +3908,7 @@ "isExactName": false }, { - "$id": "327", + "$id": "343", "kind": "property", "name": "readOnlyOptionalRecordUnknown", "apiVersions": [ @@ -3724,7 +3918,7 @@ "serializedName": "readOnlyOptionalRecordUnknown", "doc": "optional readonly record of unknown", "type": { - "$ref": "322" + "$ref": "338" }, "optional": true, "readOnly": true, @@ -3741,7 +3935,7 @@ "isExactName": false }, { - "$id": "328", + "$id": "344", "kind": "property", "name": "modelWithRequiredNullable", "apiVersions": [ @@ -3751,7 +3945,7 @@ "serializedName": "modelWithRequiredNullable", "doc": "this is a model with required nullable properties", "type": { - "$id": "329", + "$id": "345", "kind": "model", "name": "ModelWithRequiredNullableProperties", "apiVersions": [ @@ -3771,7 +3965,7 @@ "isExactName": false, "properties": [ { - "$id": "330", + "$id": "346", "kind": "property", "name": "requiredNullablePrimitive", "apiVersions": [ @@ -3781,10 +3975,10 @@ "serializedName": "requiredNullablePrimitive", "doc": "required nullable primitive type", "type": { - "$id": "331", + "$id": "347", "kind": "nullable", "type": { - "$id": "332", + "$id": "348", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -3807,7 +4001,7 @@ "isExactName": false }, { - "$id": "333", + "$id": "349", "kind": "property", "name": "requiredExtensibleEnum", "apiVersions": [ @@ -3817,7 +4011,7 @@ "serializedName": "requiredExtensibleEnum", "doc": "required nullable extensible enum type", "type": { - "$id": "334", + "$id": "350", "kind": "nullable", "type": { "$ref": "22" @@ -3839,7 +4033,7 @@ "isExactName": false }, { - "$id": "335", + "$id": "351", "kind": "property", "name": "requiredFixedEnum", "apiVersions": [ @@ -3849,7 +4043,7 @@ "serializedName": "requiredFixedEnum", "doc": "required nullable fixed enum type", "type": { - "$id": "336", + "$id": "352", "kind": "nullable", "type": { "$ref": "17" @@ -3887,7 +4081,7 @@ "isExactName": false }, { - "$id": "337", + "$id": "353", "kind": "property", "name": "requiredBytes", "apiVersions": [ @@ -3897,7 +4091,7 @@ "serializedName": "requiredBytes", "doc": "Required bytes", "type": { - "$id": "338", + "$id": "354", "kind": "bytes", "name": "bytes", "encode": "base64", @@ -3921,10 +4115,10 @@ ] }, { - "$ref": "329" + "$ref": "345" }, { - "$id": "339", + "$id": "355", "kind": "model", "name": "Wrapper", "apiVersions": [ @@ -3939,7 +4133,7 @@ "isExactName": false, "properties": [ { - "$id": "340", + "$id": "356", "kind": "property", "name": "p1", "apiVersions": [ @@ -3948,7 +4142,7 @@ ], "doc": "header parameter", "type": { - "$id": "341", + "$id": "357", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -3965,7 +4159,7 @@ "isExactName": false }, { - "$id": "342", + "$id": "358", "kind": "property", "name": "action", "apiVersions": [ @@ -3974,7 +4168,7 @@ ], "doc": "body parameter", "type": { - "$ref": "291" + "$ref": "307" }, "optional": false, "readOnly": false, @@ -3987,7 +4181,7 @@ "isExactName": false }, { - "$id": "343", + "$id": "359", "kind": "property", "name": "p2", "apiVersions": [ @@ -3996,7 +4190,7 @@ ], "doc": "path parameter", "type": { - "$id": "344", + "$id": "360", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -4015,7 +4209,7 @@ ] }, { - "$id": "345", + "$id": "361", "kind": "model", "name": "Friend", "apiVersions": [ @@ -4035,7 +4229,7 @@ "isExactName": false, "properties": [ { - "$id": "346", + "$id": "362", "kind": "property", "name": "name", "apiVersions": [ @@ -4045,7 +4239,7 @@ "serializedName": "name", "doc": "name of the NotFriend", "type": { - "$id": "347", + "$id": "363", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -4068,7 +4262,7 @@ ] }, { - "$id": "348", + "$id": "364", "kind": "model", "name": "RenamedModel", "apiVersions": [ @@ -4088,7 +4282,7 @@ "isExactName": false, "properties": [ { - "$id": "349", + "$id": "365", "kind": "property", "name": "otherName", "apiVersions": [ @@ -4098,7 +4292,7 @@ "serializedName": "otherName", "doc": "name of the ModelWithClientName", "type": { - "$id": "350", + "$id": "366", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -4121,7 +4315,7 @@ ] }, { - "$id": "351", + "$id": "367", "kind": "model", "name": "ReturnsAnonymousModelResponse", "apiVersions": [ @@ -4141,7 +4335,7 @@ "properties": [] }, { - "$id": "352", + "$id": "368", "kind": "model", "name": "ListWithNextLinkResponse", "apiVersions": [ @@ -4160,7 +4354,7 @@ "isExactName": false, "properties": [ { - "$id": "353", + "$id": "369", "kind": "property", "name": "things", "apiVersions": [ @@ -4169,11 +4363,11 @@ ], "serializedName": "things", "type": { - "$id": "354", + "$id": "370", "kind": "array", "name": "ArrayThing", "valueType": { - "$ref": "256" + "$ref": "272" }, "crossLanguageDefinitionId": "TypeSpec.Array", "decorators": [] @@ -4193,7 +4387,7 @@ "isExactName": false }, { - "$id": "355", + "$id": "371", "kind": "property", "name": "next", "apiVersions": [ @@ -4202,7 +4396,7 @@ ], "serializedName": "next", "type": { - "$id": "356", + "$id": "372", "kind": "url", "name": "url", "crossLanguageDefinitionId": "TypeSpec.url", @@ -4225,7 +4419,7 @@ ] }, { - "$id": "357", + "$id": "373", "kind": "model", "name": "ListWithStringNextLinkResponse", "apiVersions": [ @@ -4244,7 +4438,7 @@ "isExactName": false, "properties": [ { - "$id": "358", + "$id": "374", "kind": "property", "name": "things", "apiVersions": [ @@ -4253,7 +4447,7 @@ ], "serializedName": "things", "type": { - "$ref": "354" + "$ref": "370" }, "optional": false, "readOnly": false, @@ -4270,7 +4464,7 @@ "isExactName": false }, { - "$id": "359", + "$id": "375", "kind": "property", "name": "next", "apiVersions": [ @@ -4279,7 +4473,7 @@ ], "serializedName": "next", "type": { - "$id": "360", + "$id": "376", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -4302,7 +4496,7 @@ ] }, { - "$id": "361", + "$id": "377", "kind": "model", "name": "ListWithContinuationTokenResponse", "apiVersions": [ @@ -4321,7 +4515,7 @@ "isExactName": false, "properties": [ { - "$id": "362", + "$id": "378", "kind": "property", "name": "things", "apiVersions": [ @@ -4330,7 +4524,7 @@ ], "serializedName": "things", "type": { - "$ref": "354" + "$ref": "370" }, "optional": false, "readOnly": false, @@ -4347,7 +4541,7 @@ "isExactName": false }, { - "$id": "363", + "$id": "379", "kind": "property", "name": "nextToken", "apiVersions": [ @@ -4356,7 +4550,7 @@ ], "serializedName": "nextToken", "type": { - "$id": "364", + "$id": "380", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -4379,7 +4573,7 @@ ] }, { - "$id": "365", + "$id": "381", "kind": "model", "name": "ListWithContinuationTokenHeaderResponseResponse", "apiVersions": [], @@ -4395,7 +4589,7 @@ "isExactName": false, "properties": [ { - "$id": "366", + "$id": "382", "kind": "property", "name": "things", "apiVersions": [ @@ -4404,7 +4598,7 @@ ], "serializedName": "things", "type": { - "$ref": "354" + "$ref": "370" }, "optional": false, "readOnly": false, @@ -4423,7 +4617,7 @@ ] }, { - "$id": "367", + "$id": "383", "kind": "model", "name": "PageThing", "apiVersions": [ @@ -4442,7 +4636,7 @@ "isExactName": false, "properties": [ { - "$id": "368", + "$id": "384", "kind": "property", "name": "items", "apiVersions": [ @@ -4451,7 +4645,7 @@ ], "serializedName": "items", "type": { - "$ref": "354" + "$ref": "370" }, "optional": false, "readOnly": false, @@ -4470,7 +4664,7 @@ ] }, { - "$id": "369", + "$id": "385", "kind": "model", "name": "ModelWithEmbeddedNonBodyParameters", "apiVersions": [ @@ -4489,7 +4683,7 @@ "isExactName": false, "properties": [ { - "$id": "370", + "$id": "386", "kind": "property", "name": "name", "apiVersions": [ @@ -4499,7 +4693,7 @@ "serializedName": "name", "doc": "name of the ModelWithEmbeddedNonBodyParameters", "type": { - "$id": "371", + "$id": "387", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -4520,7 +4714,7 @@ "isExactName": false }, { - "$id": "372", + "$id": "388", "kind": "property", "name": "requiredHeader", "apiVersions": [ @@ -4530,7 +4724,7 @@ "serializedName": "requiredHeader", "doc": "required header parameter", "type": { - "$id": "373", + "$id": "389", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -4551,7 +4745,7 @@ "isExactName": false }, { - "$id": "374", + "$id": "390", "kind": "property", "name": "optionalHeader", "apiVersions": [ @@ -4561,7 +4755,7 @@ "serializedName": "optionalHeader", "doc": "optional header parameter", "type": { - "$id": "375", + "$id": "391", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -4582,7 +4776,7 @@ "isExactName": false }, { - "$id": "376", + "$id": "392", "kind": "property", "name": "requiredQuery", "apiVersions": [ @@ -4592,7 +4786,7 @@ "serializedName": "requiredQuery", "doc": "required query parameter", "type": { - "$id": "377", + "$id": "393", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -4613,7 +4807,7 @@ "isExactName": false }, { - "$id": "378", + "$id": "394", "kind": "property", "name": "optionalQuery", "apiVersions": [ @@ -4623,7 +4817,7 @@ "serializedName": "optionalQuery", "doc": "optional query parameter", "type": { - "$id": "379", + "$id": "395", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -4646,7 +4840,7 @@ ] }, { - "$id": "380", + "$id": "396", "kind": "model", "name": "DynamicModel", "apiVersions": [ @@ -4671,7 +4865,7 @@ "isExactName": false, "properties": [ { - "$id": "381", + "$id": "397", "kind": "property", "name": "name", "apiVersions": [ @@ -4680,7 +4874,7 @@ ], "serializedName": "name", "type": { - "$id": "382", + "$id": "398", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -4701,7 +4895,7 @@ "isExactName": false }, { - "$id": "383", + "$id": "399", "kind": "property", "name": "optionalUnknown", "apiVersions": [ @@ -4710,7 +4904,7 @@ ], "serializedName": "optionalUnknown", "type": { - "$id": "384", + "$id": "400", "kind": "unknown", "name": "unknown", "crossLanguageDefinitionId": "", @@ -4731,7 +4925,7 @@ "isExactName": false }, { - "$id": "385", + "$id": "401", "kind": "property", "name": "optionalInt", "apiVersions": [ @@ -4740,7 +4934,7 @@ ], "serializedName": "optionalInt", "type": { - "$id": "386", + "$id": "402", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -4761,7 +4955,7 @@ "isExactName": false }, { - "$id": "387", + "$id": "403", "kind": "property", "name": "optionalNullableList", "apiVersions": [ @@ -4770,10 +4964,10 @@ ], "serializedName": "optionalNullableList", "type": { - "$id": "388", + "$id": "404", "kind": "nullable", "type": { - "$ref": "285" + "$ref": "301" }, "namespace": "SampleTypeSpec" }, @@ -4792,7 +4986,7 @@ "isExactName": false }, { - "$id": "389", + "$id": "405", "kind": "property", "name": "requiredNullableList", "apiVersions": [ @@ -4801,10 +4995,10 @@ ], "serializedName": "requiredNullableList", "type": { - "$id": "390", + "$id": "406", "kind": "nullable", "type": { - "$ref": "285" + "$ref": "301" }, "namespace": "SampleTypeSpec" }, @@ -4823,7 +5017,7 @@ "isExactName": false }, { - "$id": "391", + "$id": "407", "kind": "property", "name": "optionalNullableDictionary", "apiVersions": [ @@ -4832,20 +5026,20 @@ ], "serializedName": "optionalNullableDictionary", "type": { - "$id": "392", + "$id": "408", "kind": "nullable", "type": { - "$id": "393", + "$id": "409", "kind": "dict", "keyType": { - "$id": "394", + "$id": "410", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, "valueType": { - "$id": "395", + "$id": "411", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -4870,7 +5064,7 @@ "isExactName": false }, { - "$id": "396", + "$id": "412", "kind": "property", "name": "requiredNullableDictionary", "apiVersions": [ @@ -4879,10 +5073,10 @@ ], "serializedName": "requiredNullableDictionary", "type": { - "$id": "397", + "$id": "413", "kind": "nullable", "type": { - "$ref": "393" + "$ref": "409" }, "namespace": "SampleTypeSpec" }, @@ -4901,7 +5095,7 @@ "isExactName": false }, { - "$id": "398", + "$id": "414", "kind": "property", "name": "primitiveDictionary", "apiVersions": [ @@ -4910,7 +5104,7 @@ ], "serializedName": "primitiveDictionary", "type": { - "$ref": "393" + "$ref": "409" }, "optional": false, "readOnly": false, @@ -4927,7 +5121,7 @@ "isExactName": false }, { - "$id": "399", + "$id": "415", "kind": "property", "name": "foo", "apiVersions": [ @@ -4936,7 +5130,7 @@ ], "serializedName": "foo", "type": { - "$id": "400", + "$id": "416", "kind": "model", "name": "AnotherDynamicModel", "apiVersions": [ @@ -4961,7 +5155,7 @@ "isExactName": false, "properties": [ { - "$id": "401", + "$id": "417", "kind": "property", "name": "bar", "apiVersions": [ @@ -4970,7 +5164,7 @@ ], "serializedName": "bar", "type": { - "$id": "402", + "$id": "418", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -5007,7 +5201,7 @@ "isExactName": false }, { - "$id": "403", + "$id": "419", "kind": "property", "name": "listFoo", "apiVersions": [ @@ -5016,11 +5210,11 @@ ], "serializedName": "listFoo", "type": { - "$id": "404", + "$id": "420", "kind": "array", "name": "ArrayAnotherDynamicModel", "valueType": { - "$ref": "400" + "$ref": "416" }, "crossLanguageDefinitionId": "TypeSpec.Array", "decorators": [] @@ -5040,7 +5234,7 @@ "isExactName": false }, { - "$id": "405", + "$id": "421", "kind": "property", "name": "listOfListFoo", "apiVersions": [ @@ -5049,11 +5243,11 @@ ], "serializedName": "listOfListFoo", "type": { - "$id": "406", + "$id": "422", "kind": "array", "name": "ArrayArray", "valueType": { - "$ref": "404" + "$ref": "420" }, "crossLanguageDefinitionId": "TypeSpec.Array", "decorators": [] @@ -5073,7 +5267,7 @@ "isExactName": false }, { - "$id": "407", + "$id": "423", "kind": "property", "name": "dictionaryFoo", "apiVersions": [ @@ -5082,17 +5276,17 @@ ], "serializedName": "dictionaryFoo", "type": { - "$id": "408", + "$id": "424", "kind": "dict", "keyType": { - "$id": "409", + "$id": "425", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, "valueType": { - "$ref": "400" + "$ref": "416" }, "decorators": [] }, @@ -5111,7 +5305,7 @@ "isExactName": false }, { - "$id": "410", + "$id": "426", "kind": "property", "name": "dictionaryOfDictionaryFoo", "apiVersions": [ @@ -5120,17 +5314,17 @@ ], "serializedName": "dictionaryOfDictionaryFoo", "type": { - "$id": "411", + "$id": "427", "kind": "dict", "keyType": { - "$id": "412", + "$id": "428", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, "valueType": { - "$ref": "408" + "$ref": "424" }, "decorators": [] }, @@ -5149,7 +5343,7 @@ "isExactName": false }, { - "$id": "413", + "$id": "429", "kind": "property", "name": "dictionaryListFoo", "apiVersions": [ @@ -5158,17 +5352,17 @@ ], "serializedName": "dictionaryListFoo", "type": { - "$id": "414", + "$id": "430", "kind": "dict", "keyType": { - "$id": "415", + "$id": "431", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, "valueType": { - "$ref": "404" + "$ref": "420" }, "decorators": [] }, @@ -5187,7 +5381,7 @@ "isExactName": false }, { - "$id": "416", + "$id": "432", "kind": "property", "name": "listOfDictionaryFoo", "apiVersions": [ @@ -5196,11 +5390,11 @@ ], "serializedName": "listOfDictionaryFoo", "type": { - "$id": "417", + "$id": "433", "kind": "array", "name": "ArrayRecord", "valueType": { - "$ref": "408" + "$ref": "424" }, "crossLanguageDefinitionId": "TypeSpec.Array", "decorators": [] @@ -5222,10 +5416,10 @@ ] }, { - "$ref": "400" + "$ref": "416" }, { - "$id": "418", + "$id": "434", "kind": "model", "name": "XmlAdvancedModel", "apiVersions": [ @@ -5254,7 +5448,7 @@ "isExactName": false, "properties": [ { - "$id": "419", + "$id": "435", "kind": "property", "name": "name", "apiVersions": [ @@ -5264,7 +5458,7 @@ "serializedName": "name", "doc": "A simple string property", "type": { - "$id": "420", + "$id": "436", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -5287,7 +5481,7 @@ "isExactName": false }, { - "$id": "421", + "$id": "437", "kind": "property", "name": "age", "apiVersions": [ @@ -5297,7 +5491,7 @@ "serializedName": "age", "doc": "An integer property", "type": { - "$id": "422", + "$id": "438", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -5320,7 +5514,7 @@ "isExactName": false }, { - "$id": "423", + "$id": "439", "kind": "property", "name": "enabled", "apiVersions": [ @@ -5330,7 +5524,7 @@ "serializedName": "enabled", "doc": "A boolean property", "type": { - "$id": "424", + "$id": "440", "kind": "boolean", "name": "boolean", "crossLanguageDefinitionId": "TypeSpec.boolean", @@ -5353,7 +5547,7 @@ "isExactName": false }, { - "$id": "425", + "$id": "441", "kind": "property", "name": "score", "apiVersions": [ @@ -5363,7 +5557,7 @@ "serializedName": "score", "doc": "A float property", "type": { - "$id": "426", + "$id": "442", "kind": "float32", "name": "float32", "crossLanguageDefinitionId": "TypeSpec.float32", @@ -5386,7 +5580,7 @@ "isExactName": false }, { - "$id": "427", + "$id": "443", "kind": "property", "name": "optionalString", "apiVersions": [ @@ -5396,7 +5590,7 @@ "serializedName": "optionalString", "doc": "An optional string", "type": { - "$id": "428", + "$id": "444", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -5419,7 +5613,7 @@ "isExactName": false }, { - "$id": "429", + "$id": "445", "kind": "property", "name": "optionalInt", "apiVersions": [ @@ -5429,7 +5623,7 @@ "serializedName": "optionalInt", "doc": "An optional integer", "type": { - "$id": "430", + "$id": "446", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -5452,7 +5646,7 @@ "isExactName": false }, { - "$id": "431", + "$id": "447", "kind": "property", "name": "nullableString", "apiVersions": [ @@ -5462,10 +5656,10 @@ "serializedName": "nullableString", "doc": "A nullable string", "type": { - "$id": "432", + "$id": "448", "kind": "nullable", "type": { - "$id": "433", + "$id": "449", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -5490,7 +5684,7 @@ "isExactName": false }, { - "$id": "434", + "$id": "450", "kind": "property", "name": "id", "apiVersions": [ @@ -5500,7 +5694,7 @@ "serializedName": "id", "doc": "A string as XML attribute", "type": { - "$id": "435", + "$id": "451", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -5528,7 +5722,7 @@ "isExactName": false }, { - "$id": "436", + "$id": "452", "kind": "property", "name": "version", "apiVersions": [ @@ -5538,7 +5732,7 @@ "serializedName": "version", "doc": "An integer as XML attribute", "type": { - "$id": "437", + "$id": "453", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -5566,7 +5760,7 @@ "isExactName": false }, { - "$id": "438", + "$id": "454", "kind": "property", "name": "isActive", "apiVersions": [ @@ -5576,7 +5770,7 @@ "serializedName": "isActive", "doc": "A boolean as XML attribute", "type": { - "$id": "439", + "$id": "455", "kind": "boolean", "name": "boolean", "crossLanguageDefinitionId": "TypeSpec.boolean", @@ -5604,7 +5798,7 @@ "isExactName": false }, { - "$id": "440", + "$id": "456", "kind": "property", "name": "originalName", "apiVersions": [ @@ -5614,7 +5808,7 @@ "serializedName": "RenamedProperty", "doc": "A property with a custom XML element name", "type": { - "$id": "441", + "$id": "457", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -5644,7 +5838,7 @@ "isExactName": false }, { - "$id": "442", + "$id": "458", "kind": "property", "name": "xmlIdentifier", "apiVersions": [ @@ -5654,7 +5848,7 @@ "serializedName": "xml-id", "doc": "An attribute with a custom XML name", "type": { - "$id": "443", + "$id": "459", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -5688,7 +5882,7 @@ "isExactName": false }, { - "$id": "444", + "$id": "460", "kind": "property", "name": "content", "apiVersions": [ @@ -5698,7 +5892,7 @@ "serializedName": "content", "doc": "Text content in the element (unwrapped string)", "type": { - "$id": "445", + "$id": "461", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -5726,7 +5920,7 @@ "isExactName": false }, { - "$id": "446", + "$id": "462", "kind": "property", "name": "unwrappedStrings", "apiVersions": [ @@ -5736,7 +5930,7 @@ "serializedName": "unwrappedStrings", "doc": "An unwrapped array of strings - items appear directly without wrapper", "type": { - "$ref": "262" + "$ref": "278" }, "optional": false, "readOnly": false, @@ -5761,7 +5955,7 @@ "isExactName": false }, { - "$id": "447", + "$id": "463", "kind": "property", "name": "unwrappedCounts", "apiVersions": [ @@ -5771,7 +5965,7 @@ "serializedName": "unwrappedCounts", "doc": "An unwrapped array of integers", "type": { - "$ref": "285" + "$ref": "301" }, "optional": false, "readOnly": false, @@ -5796,7 +5990,7 @@ "isExactName": false }, { - "$id": "448", + "$id": "464", "kind": "property", "name": "unwrappedItems", "apiVersions": [ @@ -5806,11 +6000,11 @@ "serializedName": "unwrappedItems", "doc": "An unwrapped array of models", "type": { - "$id": "449", + "$id": "465", "kind": "array", "name": "ArrayXmlItem", "valueType": { - "$id": "450", + "$id": "466", "kind": "model", "name": "XmlItem", "apiVersions": [ @@ -5839,7 +6033,7 @@ "isExactName": false, "properties": [ { - "$id": "451", + "$id": "467", "kind": "property", "name": "itemName", "apiVersions": [ @@ -5849,7 +6043,7 @@ "serializedName": "itemName", "doc": "The item name", "type": { - "$id": "452", + "$id": "468", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -5872,7 +6066,7 @@ "isExactName": false }, { - "$id": "453", + "$id": "469", "kind": "property", "name": "itemValue", "apiVersions": [ @@ -5882,7 +6076,7 @@ "serializedName": "itemValue", "doc": "The item value", "type": { - "$id": "454", + "$id": "470", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -5905,7 +6099,7 @@ "isExactName": false }, { - "$id": "455", + "$id": "471", "kind": "property", "name": "itemId", "apiVersions": [ @@ -5915,7 +6109,7 @@ "serializedName": "itemId", "doc": "Item ID as attribute", "type": { - "$id": "456", + "$id": "472", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -5970,7 +6164,7 @@ "isExactName": false }, { - "$id": "457", + "$id": "473", "kind": "property", "name": "wrappedColors", "apiVersions": [ @@ -5980,7 +6174,7 @@ "serializedName": "wrappedColors", "doc": "A wrapped array of strings (default)", "type": { - "$ref": "262" + "$ref": "278" }, "optional": false, "readOnly": false, @@ -6000,7 +6194,7 @@ "isExactName": false }, { - "$id": "458", + "$id": "474", "kind": "property", "name": "items", "apiVersions": [ @@ -6010,7 +6204,7 @@ "serializedName": "ItemCollection", "doc": "A wrapped array with custom wrapper name", "type": { - "$ref": "449" + "$ref": "465" }, "optional": false, "readOnly": false, @@ -6037,7 +6231,7 @@ "isExactName": false }, { - "$id": "459", + "$id": "475", "kind": "property", "name": "nestedModel", "apiVersions": [ @@ -6047,7 +6241,7 @@ "serializedName": "nestedModel", "doc": "A nested model property", "type": { - "$id": "460", + "$id": "476", "kind": "model", "name": "XmlNestedModel", "apiVersions": [ @@ -6069,7 +6263,7 @@ "isExactName": false, "properties": [ { - "$id": "461", + "$id": "477", "kind": "property", "name": "value", "apiVersions": [ @@ -6079,7 +6273,7 @@ "serializedName": "value", "doc": "The value of the nested model", "type": { - "$id": "462", + "$id": "478", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -6102,7 +6296,7 @@ "isExactName": false }, { - "$id": "463", + "$id": "479", "kind": "property", "name": "nestedId", "apiVersions": [ @@ -6112,7 +6306,7 @@ "serializedName": "nestedId", "doc": "An attribute on the nested model", "type": { - "$id": "464", + "$id": "480", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -6158,7 +6352,7 @@ "isExactName": false }, { - "$id": "465", + "$id": "481", "kind": "property", "name": "optionalNestedModel", "apiVersions": [ @@ -6168,7 +6362,7 @@ "serializedName": "optionalNestedModel", "doc": "An optional nested model", "type": { - "$ref": "460" + "$ref": "476" }, "optional": true, "readOnly": false, @@ -6187,7 +6381,7 @@ "isExactName": false }, { - "$id": "466", + "$id": "482", "kind": "property", "name": "metadata", "apiVersions": [ @@ -6197,17 +6391,17 @@ "serializedName": "metadata", "doc": "A dictionary property", "type": { - "$id": "467", + "$id": "483", "kind": "dict", "keyType": { - "$id": "468", + "$id": "484", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, "valueType": { - "$id": "469", + "$id": "485", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -6232,7 +6426,7 @@ "isExactName": false }, { - "$id": "470", + "$id": "486", "kind": "property", "name": "createdAt", "apiVersions": [ @@ -6242,12 +6436,12 @@ "serializedName": "createdAt", "doc": "A date-time property", "type": { - "$id": "471", + "$id": "487", "kind": "utcDateTime", "name": "utcDateTime", "encode": "rfc3339", "wireType": { - "$id": "472", + "$id": "488", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -6273,7 +6467,7 @@ "isExactName": false }, { - "$id": "473", + "$id": "489", "kind": "property", "name": "duration", "apiVersions": [ @@ -6283,12 +6477,12 @@ "serializedName": "duration", "doc": "A duration property", "type": { - "$id": "474", + "$id": "490", "kind": "duration", "name": "duration", "encode": "ISO8601", "wireType": { - "$id": "475", + "$id": "491", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -6314,7 +6508,7 @@ "isExactName": false }, { - "$id": "476", + "$id": "492", "kind": "property", "name": "data", "apiVersions": [ @@ -6324,7 +6518,7 @@ "serializedName": "data", "doc": "A bytes property", "type": { - "$id": "477", + "$id": "493", "kind": "bytes", "name": "bytes", "encode": "base64", @@ -6348,7 +6542,7 @@ "isExactName": false }, { - "$id": "478", + "$id": "494", "kind": "property", "name": "optionalRecordUnknown", "apiVersions": [ @@ -6358,7 +6552,7 @@ "serializedName": "optionalRecordUnknown", "doc": "optional record of unknown", "type": { - "$ref": "322" + "$ref": "338" }, "optional": true, "readOnly": false, @@ -6377,7 +6571,7 @@ "isExactName": false }, { - "$id": "479", + "$id": "495", "kind": "property", "name": "fixedEnum", "apiVersions": [ @@ -6406,7 +6600,7 @@ "isExactName": false }, { - "$id": "480", + "$id": "496", "kind": "property", "name": "extensibleEnum", "apiVersions": [ @@ -6435,7 +6629,7 @@ "isExactName": false }, { - "$id": "481", + "$id": "497", "kind": "property", "name": "optionalFixedEnum", "apiVersions": [ @@ -6464,7 +6658,7 @@ "isExactName": false }, { - "$id": "482", + "$id": "498", "kind": "property", "name": "optionalExtensibleEnum", "apiVersions": [ @@ -6493,7 +6687,7 @@ "isExactName": false }, { - "$id": "483", + "$id": "499", "kind": "property", "name": "label", "apiVersions": [ @@ -6502,7 +6696,7 @@ ], "serializedName": "label", "type": { - "$id": "484", + "$id": "500", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -6517,14 +6711,14 @@ "name": "TypeSpec.Xml.@ns", "arguments": { "ns": { - "$id": "485", + "$id": "501", "kind": "enumvalue", "decorators": [], "name": "ns1", "isExactName": false, "value": "https://example.com/ns1", "enumType": { - "$id": "486", + "$id": "502", "kind": "enum", "decorators": [ { @@ -6537,7 +6731,7 @@ "isExactName": false, "namespace": "SampleTypeSpec", "valueType": { - "$id": "487", + "$id": "503", "kind": "string", "decorators": [], "doc": "A sequence of textual characters.", @@ -6546,32 +6740,32 @@ }, "values": [ { - "$id": "488", + "$id": "504", "kind": "enumvalue", "decorators": [], "name": "ns1", "isExactName": false, "value": "https://example.com/ns1", "enumType": { - "$ref": "486" + "$ref": "502" }, "valueType": { - "$ref": "487" + "$ref": "503" }, "crossLanguageDefinitionId": "SampleTypeSpec.XmlNamespaces.ns1" }, { - "$id": "489", + "$id": "505", "kind": "enumvalue", "decorators": [], "name": "ns2", "isExactName": false, "value": "https://example.com/ns2", "enumType": { - "$ref": "486" + "$ref": "502" }, "valueType": { - "$ref": "487" + "$ref": "503" }, "crossLanguageDefinitionId": "SampleTypeSpec.XmlNamespaces.ns2" } @@ -6589,7 +6783,7 @@ "__accessSet": true }, "valueType": { - "$ref": "487" + "$ref": "503" }, "crossLanguageDefinitionId": "SampleTypeSpec.XmlNamespaces.ns1" } @@ -6616,7 +6810,7 @@ "isExactName": false }, { - "$id": "490", + "$id": "506", "kind": "property", "name": "daysUsed", "apiVersions": [ @@ -6625,7 +6819,7 @@ ], "serializedName": "daysUsed", "type": { - "$id": "491", + "$id": "507", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -6640,17 +6834,17 @@ "name": "TypeSpec.Xml.@ns", "arguments": { "ns": { - "$id": "492", + "$id": "508", "kind": "enumvalue", "decorators": [], "name": "ns2", "isExactName": false, "value": "https://example.com/ns2", "enumType": { - "$ref": "486" + "$ref": "502" }, "valueType": { - "$ref": "487" + "$ref": "503" }, "crossLanguageDefinitionId": "SampleTypeSpec.XmlNamespaces.ns2" } @@ -6673,7 +6867,7 @@ "isExactName": false }, { - "$id": "493", + "$id": "509", "kind": "property", "name": "fooItems", "apiVersions": [ @@ -6682,7 +6876,7 @@ ], "serializedName": "fooItems", "type": { - "$ref": "262" + "$ref": "278" }, "optional": false, "readOnly": false, @@ -6714,7 +6908,7 @@ "isExactName": false }, { - "$id": "494", + "$id": "510", "kind": "property", "name": "anotherModel", "apiVersions": [ @@ -6723,7 +6917,7 @@ ], "serializedName": "anotherModel", "type": { - "$ref": "460" + "$ref": "476" }, "optional": false, "readOnly": false, @@ -6754,7 +6948,7 @@ "isExactName": false }, { - "$id": "495", + "$id": "511", "kind": "property", "name": "modelsWithNamespaces", "apiVersions": [ @@ -6763,11 +6957,11 @@ ], "serializedName": "modelsWithNamespaces", "type": { - "$id": "496", + "$id": "512", "kind": "array", "name": "ArrayXmlModelWithNamespace", "valueType": { - "$id": "497", + "$id": "513", "kind": "model", "name": "XmlModelWithNamespace", "apiVersions": [ @@ -6800,7 +6994,7 @@ "isExactName": false, "properties": [ { - "$id": "498", + "$id": "514", "kind": "property", "name": "foo", "apiVersions": [ @@ -6809,7 +7003,7 @@ ], "serializedName": "foo", "type": { - "$id": "499", + "$id": "515", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -6858,7 +7052,7 @@ "isExactName": false }, { - "$id": "500", + "$id": "516", "kind": "property", "name": "unwrappedModelsWithNamespaces", "apiVersions": [ @@ -6867,7 +7061,7 @@ ], "serializedName": "unwrappedModelsWithNamespaces", "type": { - "$ref": "496" + "$ref": "512" }, "optional": false, "readOnly": false, @@ -6892,7 +7086,7 @@ "isExactName": false }, { - "$id": "501", + "$id": "517", "kind": "property", "name": "listOfListFoo", "apiVersions": [ @@ -6901,11 +7095,11 @@ ], "serializedName": "listOfListFoo", "type": { - "$id": "502", + "$id": "518", "kind": "array", "name": "ArrayArray1", "valueType": { - "$ref": "449" + "$ref": "465" }, "crossLanguageDefinitionId": "TypeSpec.Array", "decorators": [] @@ -6928,7 +7122,7 @@ "isExactName": false }, { - "$id": "503", + "$id": "519", "kind": "property", "name": "dictionaryFoo", "apiVersions": [ @@ -6937,17 +7131,17 @@ ], "serializedName": "dictionaryFoo", "type": { - "$id": "504", + "$id": "520", "kind": "dict", "keyType": { - "$id": "505", + "$id": "521", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, "valueType": { - "$ref": "450" + "$ref": "466" }, "decorators": [] }, @@ -6968,7 +7162,7 @@ "isExactName": false }, { - "$id": "506", + "$id": "522", "kind": "property", "name": "dictionaryOfDictionaryFoo", "apiVersions": [ @@ -6977,17 +7171,17 @@ ], "serializedName": "dictionaryOfDictionaryFoo", "type": { - "$id": "507", + "$id": "523", "kind": "dict", "keyType": { - "$id": "508", + "$id": "524", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, "valueType": { - "$ref": "504" + "$ref": "520" }, "decorators": [] }, @@ -7008,7 +7202,7 @@ "isExactName": false }, { - "$id": "509", + "$id": "525", "kind": "property", "name": "dictionaryListFoo", "apiVersions": [ @@ -7017,17 +7211,17 @@ ], "serializedName": "dictionaryListFoo", "type": { - "$id": "510", + "$id": "526", "kind": "dict", "keyType": { - "$id": "511", + "$id": "527", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, "valueType": { - "$ref": "449" + "$ref": "465" }, "decorators": [] }, @@ -7048,7 +7242,7 @@ "isExactName": false }, { - "$id": "512", + "$id": "528", "kind": "property", "name": "listOfDictionaryFoo", "apiVersions": [ @@ -7057,11 +7251,11 @@ ], "serializedName": "listOfDictionaryFoo", "type": { - "$id": "513", + "$id": "529", "kind": "array", "name": "ArrayRecord1", "valueType": { - "$ref": "504" + "$ref": "520" }, "crossLanguageDefinitionId": "TypeSpec.Array", "decorators": [] @@ -7086,16 +7280,16 @@ ] }, { - "$ref": "450" + "$ref": "466" }, { - "$ref": "460" + "$ref": "476" }, { - "$ref": "497" + "$ref": "513" }, { - "$id": "514", + "$id": "530", "kind": "model", "name": "Cat", "apiVersions": [ @@ -7110,7 +7304,7 @@ "isExactName": false, "properties": [ { - "$id": "515", + "$id": "531", "kind": "property", "name": "id", "apiVersions": [ @@ -7119,7 +7313,7 @@ ], "serializedName": "id", "type": { - "$id": "516", + "$id": "532", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -7146,7 +7340,7 @@ "isExactName": false }, { - "$id": "517", + "$id": "533", "kind": "property", "name": "boolPart", "apiVersions": [ @@ -7155,7 +7349,7 @@ ], "serializedName": "boolPart", "type": { - "$id": "518", + "$id": "534", "kind": "boolean", "name": "boolean", "crossLanguageDefinitionId": "TypeSpec.boolean", @@ -7182,7 +7376,7 @@ "isExactName": false }, { - "$id": "519", + "$id": "535", "kind": "property", "name": "int32Part", "apiVersions": [ @@ -7191,7 +7385,7 @@ ], "serializedName": "int32Part", "type": { - "$id": "520", + "$id": "536", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -7218,7 +7412,7 @@ "isExactName": false }, { - "$id": "521", + "$id": "537", "kind": "property", "name": "int64Part", "apiVersions": [ @@ -7227,7 +7421,7 @@ ], "serializedName": "int64Part", "type": { - "$id": "522", + "$id": "538", "kind": "int64", "name": "int64", "crossLanguageDefinitionId": "TypeSpec.int64", @@ -7254,7 +7448,7 @@ "isExactName": false }, { - "$id": "523", + "$id": "539", "kind": "property", "name": "float32Part", "apiVersions": [ @@ -7263,7 +7457,7 @@ ], "serializedName": "float32Part", "type": { - "$id": "524", + "$id": "540", "kind": "float32", "name": "float32", "crossLanguageDefinitionId": "TypeSpec.float32", @@ -7290,7 +7484,7 @@ "isExactName": false }, { - "$id": "525", + "$id": "541", "kind": "property", "name": "float64Part", "apiVersions": [ @@ -7299,7 +7493,7 @@ ], "serializedName": "float64Part", "type": { - "$id": "526", + "$id": "542", "kind": "float64", "name": "float64", "crossLanguageDefinitionId": "TypeSpec.float64", @@ -7326,7 +7520,7 @@ "isExactName": false }, { - "$id": "527", + "$id": "543", "kind": "property", "name": "decimalPart", "apiVersions": [ @@ -7335,7 +7529,7 @@ ], "serializedName": "decimalPart", "type": { - "$id": "528", + "$id": "544", "kind": "decimal128", "name": "decimal128", "crossLanguageDefinitionId": "TypeSpec.decimal128", @@ -7362,7 +7556,7 @@ "isExactName": false }, { - "$id": "529", + "$id": "545", "kind": "property", "name": "int8Part", "apiVersions": [ @@ -7371,7 +7565,7 @@ ], "serializedName": "int8Part", "type": { - "$id": "530", + "$id": "546", "kind": "int8", "name": "int8", "crossLanguageDefinitionId": "TypeSpec.int8", @@ -7398,7 +7592,7 @@ "isExactName": false }, { - "$id": "531", + "$id": "547", "kind": "property", "name": "uint8Part", "apiVersions": [ @@ -7407,7 +7601,7 @@ ], "serializedName": "uint8Part", "type": { - "$id": "532", + "$id": "548", "kind": "uint8", "name": "uint8", "crossLanguageDefinitionId": "TypeSpec.uint8", @@ -7434,7 +7628,7 @@ "isExactName": false }, { - "$id": "533", + "$id": "549", "kind": "property", "name": "dictionaryPart", "apiVersions": [ @@ -7443,7 +7637,7 @@ ], "serializedName": "dictionaryPart", "type": { - "$ref": "467" + "$ref": "483" }, "optional": false, "readOnly": false, @@ -7466,7 +7660,7 @@ "isExactName": false }, { - "$id": "534", + "$id": "550", "kind": "property", "name": "dictionaryModelPart", "apiVersions": [ @@ -7475,17 +7669,17 @@ ], "serializedName": "dictionaryModelPart", "type": { - "$id": "535", + "$id": "551", "kind": "dict", "keyType": { - "$id": "536", + "$id": "552", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, "valueType": { - "$ref": "256" + "$ref": "272" }, "decorators": [] }, @@ -7510,7 +7704,7 @@ "isExactName": false }, { - "$id": "537", + "$id": "553", "kind": "property", "name": "listPart", "apiVersions": [ @@ -7519,7 +7713,7 @@ ], "serializedName": "listPart", "type": { - "$ref": "262" + "$ref": "278" }, "optional": false, "readOnly": false, @@ -7542,7 +7736,7 @@ "isExactName": false }, { - "$id": "538", + "$id": "554", "kind": "property", "name": "listModelPart", "apiVersions": [ @@ -7551,7 +7745,7 @@ ], "serializedName": "listModelPart", "type": { - "$ref": "354" + "$ref": "370" }, "optional": false, "readOnly": false, @@ -7574,7 +7768,7 @@ "isExactName": false }, { - "$id": "539", + "$id": "555", "kind": "property", "name": "multipleListPart", "apiVersions": [ @@ -7583,11 +7777,11 @@ ], "serializedName": "multipleListPart", "type": { - "$id": "540", + "$id": "556", "kind": "array", "name": "ArrayHttpPart", "valueType": { - "$id": "541", + "$id": "557", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -7617,7 +7811,7 @@ "isExactName": false }, { - "$id": "542", + "$id": "558", "kind": "property", "name": "profileImage", "apiVersions": [ @@ -7626,7 +7820,7 @@ ], "serializedName": "profileImage", "type": { - "$id": "543", + "$id": "559", "kind": "model", "name": "File", "apiVersions": [], @@ -7641,14 +7835,14 @@ "isFileType": true, "properties": [ { - "$id": "544", + "$id": "560", "kind": "property", "name": "contentType", "apiVersions": [], "summary": "The allowed media (MIME) types of the file contents.", "doc": "The allowed media (MIME) types of the file contents.\n\nIn file bodies, this value comes from the `Content-Type` header of the request or response. In JSON bodies,\nthis value is serialized as a field in the response.\n\nNOTE: this is not _necessarily_ the same as the `Content-Type` header of the request or response, but\nit will be for file bodies. It may be different if the file is serialized as a JSON object. It always refers to the\n_contents_ of the file, and not necessarily the way the file itself is transmitted or serialized.", "type": { - "$id": "545", + "$id": "561", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -7665,14 +7859,14 @@ "isExactName": false }, { - "$id": "546", + "$id": "562", "kind": "property", "name": "filename", "apiVersions": [], "summary": "The name of the file, if any.", "doc": "The name of the file, if any.\n\nIn file bodies, this value comes from the `filename` parameter of the `Content-Disposition` header of the response\nor multipart payload. In JSON bodies, this value is serialized as a field in the response.\n\nNOTE: By default, `filename` cannot be sent in request payloads and can only be sent in responses and multipart\npayloads, as the `Content-Disposition` header is not valid in requests. If you want to send the `filename` in a request,\nyou must extend the `File` model and override the `filename` property with a different location defined by HTTP metadata\ndecorators.", "type": { - "$id": "547", + "$id": "563", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -7689,14 +7883,14 @@ "isExactName": false }, { - "$id": "548", + "$id": "564", "kind": "property", "name": "contents", "apiVersions": [], "summary": "The contents of the file.", "doc": "The contents of the file.\n\nIn file bodies, this value comes from the body of the request, response, or multipart payload. In JSON bodies,\nthis value is serialized as a field in the response.", "type": { - "$id": "549", + "$id": "565", "kind": "bytes", "name": "bytes", "encode": "base64", @@ -7726,12 +7920,12 @@ "isFilePart": true, "isMulti": false, "filename": { - "$id": "550", + "$id": "566", "doc": "The name of the file, if any.\n\nIn file bodies, this value comes from the `filename` parameter of the `Content-Disposition` header of the response\nor multipart payload. In JSON bodies, this value is serialized as a field in the response.\n\nNOTE: By default, `filename` cannot be sent in request payloads and can only be sent in responses and multipart\npayloads, as the `Content-Disposition` header is not valid in requests. If you want to send the `filename` in a request,\nyou must extend the `File` model and override the `filename` property with a different location defined by HTTP metadata\ndecorators.", "summary": "The name of the file, if any.", "apiVersions": [], "type": { - "$id": "551", + "$id": "567", "kind": "string", "decorators": [], "doc": "A sequence of textual characters.", @@ -7762,12 +7956,12 @@ "serializationOptions": {} }, "contentType": { - "$id": "552", + "$id": "568", "doc": "The allowed media (MIME) types of the file contents.\n\nIn file bodies, this value comes from the `Content-Type` header of the request or response. In JSON bodies,\nthis value is serialized as a field in the response.\n\nNOTE: this is not _necessarily_ the same as the `Content-Type` header of the request or response, but\nit will be for file bodies. It may be different if the file is serialized as a JSON object. It always refers to the\n_contents_ of the file, and not necessarily the way the file itself is transmitted or serialized.", "summary": "The allowed media (MIME) types of the file contents.", "apiVersions": [], "type": { - "$id": "553", + "$id": "569", "kind": "string", "decorators": [], "doc": "A sequence of textual characters.", @@ -7808,7 +8002,7 @@ "isExactName": false }, { - "$id": "554", + "$id": "570", "kind": "property", "name": "extensibleEnumPart", "apiVersions": [ @@ -7840,7 +8034,7 @@ "isExactName": false }, { - "$id": "555", + "$id": "571", "kind": "property", "name": "fixedEnumPart", "apiVersions": [ @@ -7872,7 +8066,7 @@ "isExactName": false }, { - "$id": "556", + "$id": "572", "kind": "property", "name": "intExtensibleEnumPart", "apiVersions": [ @@ -7904,7 +8098,7 @@ "isExactName": false }, { - "$id": "557", + "$id": "573", "kind": "property", "name": "intFixedEnumPart", "apiVersions": [ @@ -7938,7 +8132,7 @@ ] }, { - "$id": "558", + "$id": "574", "kind": "model", "name": "File", "apiVersions": [], @@ -7953,18 +8147,18 @@ "isFileType": true, "properties": [ { - "$ref": "544" + "$ref": "560" }, { - "$ref": "546" + "$ref": "562" }, { - "$ref": "548" + "$ref": "564" } ] }, { - "$id": "559", + "$id": "575", "kind": "model", "name": "StreamingItem", "apiVersions": [ @@ -7983,7 +8177,7 @@ "isExactName": false, "properties": [ { - "$id": "560", + "$id": "576", "kind": "property", "name": "message", "apiVersions": [ @@ -7992,7 +8186,7 @@ ], "serializedName": "message", "type": { - "$id": "561", + "$id": "577", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -8015,7 +8209,193 @@ ] }, { - "$id": "562", + "$id": "578", + "kind": "model", + "name": "PreviewDetails", + "apiVersions": [ + "2024-07-16-preview", + "2024-08-16-preview" + ], + "namespace": "SampleTypeSpec", + "crossLanguageDefinitionId": "SampleTypeSpec.PreviewDetails", + "usage": "Output,Json", + "decorators": [], + "serializationOptions": { + "json": { + "name": "PreviewDetails" + } + }, + "isExactName": false, + "properties": [ + { + "$id": "579", + "kind": "property", + "name": "choice", + "apiVersions": [ + "2024-07-16-preview", + "2024-08-16-preview" + ], + "serializedName": "choice", + "type": { + "$ref": "57" + }, + "optional": false, + "readOnly": false, + "discriminator": false, + "flatten": false, + "decorators": [], + "crossLanguageDefinitionId": "SampleTypeSpec.PreviewDetails.choice", + "serializationOptions": { + "json": { + "name": "choice" + } + }, + "isHttpMetadata": false, + "isExactName": false + } + ], + "experimental": { + "diagnosticId": "SAMPLE0003", + "dependsOn": [ + "SAMPLE0004" + ] + } + }, + { + "$id": "580", + "kind": "model", + "name": "LifecycleModel", + "apiVersions": [ + "2024-07-16-preview", + "2024-08-16-preview" + ], + "namespace": "SampleTypeSpec", + "crossLanguageDefinitionId": "SampleTypeSpec.LifecycleModel", + "usage": "Output,Json", + "decorators": [], + "serializationOptions": { + "json": { + "name": "LifecycleModel" + } + }, + "isExactName": false, + "properties": [ + { + "$id": "581", + "kind": "property", + "name": "preview", + "apiVersions": [ + "2024-07-16-preview", + "2024-08-16-preview" + ], + "serializedName": "preview", + "type": { + "$ref": "578" + }, + "optional": true, + "readOnly": false, + "discriminator": false, + "flatten": false, + "decorators": [], + "crossLanguageDefinitionId": "SampleTypeSpec.LifecycleModel.preview", + "serializationOptions": { + "json": { + "name": "preview" + } + }, + "isHttpMetadata": false, + "isExactName": false, + "experimental": { + "diagnosticId": "SAMPLE0008", + "dependsOn": [ + "SAMPLE0003" + ] + } + }, + { + "$id": "582", + "kind": "property", + "name": "choice", + "apiVersions": [ + "2024-07-16-preview", + "2024-08-16-preview" + ], + "serializedName": "choice", + "type": { + "$ref": "61" + }, + "optional": false, + "readOnly": false, + "discriminator": false, + "flatten": false, + "decorators": [], + "crossLanguageDefinitionId": "SampleTypeSpec.LifecycleModel.choice", + "serializationOptions": { + "json": { + "name": "choice" + } + }, + "isHttpMetadata": false, + "isExactName": false + } + ] + }, + { + "$id": "583", + "kind": "model", + "name": "PagePreviewDetails", + "apiVersions": [ + "2024-07-16-preview", + "2024-08-16-preview" + ], + "namespace": "SampleTypeSpec", + "crossLanguageDefinitionId": "SampleTypeSpec.Page", + "usage": "Output,Json", + "decorators": [], + "serializationOptions": { + "json": { + "name": "Page" + } + }, + "isExactName": false, + "properties": [ + { + "$id": "584", + "kind": "property", + "name": "items", + "apiVersions": [ + "2024-07-16-preview", + "2024-08-16-preview" + ], + "serializedName": "items", + "type": { + "$id": "585", + "kind": "array", + "name": "ArrayPreviewDetails", + "valueType": { + "$ref": "578" + }, + "crossLanguageDefinitionId": "TypeSpec.Array", + "decorators": [] + }, + "optional": false, + "readOnly": false, + "discriminator": false, + "flatten": false, + "decorators": [], + "crossLanguageDefinitionId": "SampleTypeSpec.Page.items", + "serializationOptions": { + "json": { + "name": "items" + } + }, + "isHttpMetadata": false, + "isExactName": false + } + ] + }, + { + "$id": "586", "kind": "model", "name": "Animal", "apiVersions": [ @@ -8034,7 +8414,7 @@ }, "isExactName": false, "discriminatorProperty": { - "$id": "563", + "$id": "587", "kind": "property", "name": "kind", "apiVersions": [ @@ -8044,7 +8424,7 @@ "serializedName": "kind", "doc": "The kind of animal", "type": { - "$id": "564", + "$id": "588", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -8066,10 +8446,10 @@ }, "properties": [ { - "$ref": "563" + "$ref": "587" }, { - "$id": "565", + "$id": "589", "kind": "property", "name": "name", "apiVersions": [ @@ -8079,7 +8459,7 @@ "serializedName": "name", "doc": "Name of the animal", "type": { - "$id": "566", + "$id": "590", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -8102,7 +8482,7 @@ ], "discriminatedSubtypes": { "pet": { - "$id": "567", + "$id": "591", "kind": "model", "name": "Pet", "apiVersions": [ @@ -8122,7 +8502,7 @@ }, "isExactName": false, "discriminatorProperty": { - "$id": "568", + "$id": "592", "kind": "property", "name": "kind", "apiVersions": [ @@ -8131,7 +8511,7 @@ ], "serializedName": "kind", "type": { - "$ref": "80" + "$ref": "88" }, "optional": false, "readOnly": false, @@ -8148,14 +8528,14 @@ "isExactName": false }, "baseModel": { - "$ref": "562" + "$ref": "586" }, "properties": [ { - "$ref": "568" + "$ref": "592" }, { - "$id": "569", + "$id": "593", "kind": "property", "name": "trained", "apiVersions": [ @@ -8165,7 +8545,7 @@ "serializedName": "trained", "doc": "Whether the pet is trained", "type": { - "$id": "570", + "$id": "594", "kind": "boolean", "name": "boolean", "crossLanguageDefinitionId": "TypeSpec.boolean", @@ -8188,7 +8568,7 @@ ], "discriminatedSubtypes": { "dog": { - "$id": "571", + "$id": "595", "kind": "model", "name": "Dog", "apiVersions": [ @@ -8208,11 +8588,11 @@ }, "isExactName": false, "baseModel": { - "$ref": "567" + "$ref": "591" }, "properties": [ { - "$id": "572", + "$id": "596", "kind": "property", "name": "kind", "apiVersions": [ @@ -8221,7 +8601,7 @@ ], "serializedName": "kind", "type": { - "$ref": "82" + "$ref": "90" }, "optional": false, "readOnly": false, @@ -8238,7 +8618,7 @@ "isExactName": false }, { - "$id": "573", + "$id": "597", "kind": "property", "name": "breed", "apiVersions": [ @@ -8248,7 +8628,7 @@ "serializedName": "breed", "doc": "The breed of the dog", "type": { - "$id": "574", + "$id": "598", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -8273,18 +8653,18 @@ } }, "dog": { - "$ref": "571" + "$ref": "595" } } }, { - "$ref": "567" + "$ref": "591" }, { - "$ref": "571" + "$ref": "595" }, { - "$id": "575", + "$id": "599", "kind": "model", "name": "Tree", "apiVersions": [ @@ -8309,7 +8689,7 @@ }, "isExactName": false, "baseModel": { - "$id": "576", + "$id": "600", "kind": "model", "name": "Plant", "apiVersions": [ @@ -8333,7 +8713,7 @@ }, "isExactName": false, "discriminatorProperty": { - "$id": "577", + "$id": "601", "kind": "property", "name": "species", "apiVersions": [ @@ -8343,7 +8723,7 @@ "serializedName": "species", "doc": "The species of plant", "type": { - "$id": "578", + "$id": "602", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -8370,10 +8750,10 @@ }, "properties": [ { - "$ref": "577" + "$ref": "601" }, { - "$id": "579", + "$id": "603", "kind": "property", "name": "id", "apiVersions": [ @@ -8383,7 +8763,7 @@ "serializedName": "id", "doc": "The unique identifier of the plant", "type": { - "$id": "580", + "$id": "604", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -8409,7 +8789,7 @@ "isExactName": false }, { - "$id": "581", + "$id": "605", "kind": "property", "name": "height", "apiVersions": [ @@ -8419,7 +8799,7 @@ "serializedName": "height", "doc": "The height of the plant in centimeters", "type": { - "$id": "582", + "$id": "606", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -8447,13 +8827,13 @@ ], "discriminatedSubtypes": { "tree": { - "$ref": "575" + "$ref": "599" } } }, "properties": [ { - "$id": "583", + "$id": "607", "kind": "property", "name": "species", "apiVersions": [ @@ -8462,7 +8842,7 @@ ], "serializedName": "species", "type": { - "$ref": "84" + "$ref": "92" }, "optional": false, "readOnly": false, @@ -8484,7 +8864,7 @@ "isExactName": false }, { - "$id": "584", + "$id": "608", "kind": "property", "name": "age", "apiVersions": [ @@ -8494,7 +8874,7 @@ "serializedName": "age", "doc": "The age of the tree in years", "type": { - "$id": "585", + "$id": "609", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -8522,10 +8902,10 @@ ] }, { - "$ref": "576" + "$ref": "600" }, { - "$id": "586", + "$id": "610", "kind": "model", "name": "GetWidgetMetricsResponse", "apiVersions": [ @@ -8544,7 +8924,7 @@ "isExactName": false, "properties": [ { - "$id": "587", + "$id": "611", "kind": "property", "name": "numSold", "apiVersions": [ @@ -8553,7 +8933,7 @@ ], "serializedName": "numSold", "type": { - "$id": "588", + "$id": "612", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -8574,7 +8954,7 @@ "isExactName": false }, { - "$id": "589", + "$id": "613", "kind": "property", "name": "averagePrice", "apiVersions": [ @@ -8583,7 +8963,7 @@ ], "serializedName": "averagePrice", "type": { - "$id": "590", + "$id": "614", "kind": "float32", "name": "float32", "crossLanguageDefinitionId": "TypeSpec.float32", @@ -8606,7 +8986,7 @@ ] }, { - "$id": "591", + "$id": "615", "kind": "model", "name": "GetNotebookResponse", "apiVersions": [ @@ -8625,7 +9005,7 @@ "isExactName": false, "properties": [ { - "$id": "592", + "$id": "616", "kind": "property", "name": "name", "apiVersions": [ @@ -8634,7 +9014,7 @@ ], "serializedName": "name", "type": { - "$id": "593", + "$id": "617", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -8655,7 +9035,7 @@ "isExactName": false }, { - "$id": "594", + "$id": "618", "kind": "property", "name": "content", "apiVersions": [ @@ -8664,7 +9044,7 @@ ], "serializedName": "content", "type": { - "$id": "595", + "$id": "619", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -8687,7 +9067,7 @@ ] }, { - "$id": "596", + "$id": "620", "kind": "model", "name": "NullableDynamicModel", "apiVersions": [ @@ -8712,7 +9092,7 @@ "isExactName": false, "properties": [ { - "$id": "597", + "$id": "621", "kind": "property", "name": "modelValue", "apiVersions": [ @@ -8721,10 +9101,10 @@ ], "serializedName": "modelValue", "type": { - "$id": "598", + "$id": "622", "kind": "nullable", "type": { - "$ref": "400" + "$ref": "416" }, "namespace": "SampleTypeSpec" }, @@ -8743,7 +9123,7 @@ "isExactName": false }, { - "$id": "599", + "$id": "623", "kind": "property", "name": "children", "apiVersions": [ @@ -8752,17 +9132,17 @@ ], "serializedName": "children", "type": { - "$id": "600", + "$id": "624", "kind": "nullable", "type": { - "$id": "601", + "$id": "625", "kind": "array", "name": "Array2", "valueType": { - "$id": "602", + "$id": "626", "kind": "nullable", "type": { - "$ref": "400" + "$ref": "416" }, "namespace": "SampleTypeSpec" }, @@ -8786,7 +9166,7 @@ "isExactName": false }, { - "$id": "603", + "$id": "627", "kind": "property", "name": "childDictionary", "apiVersions": [ @@ -8795,23 +9175,23 @@ ], "serializedName": "childDictionary", "type": { - "$id": "604", + "$id": "628", "kind": "nullable", "type": { - "$id": "605", + "$id": "629", "kind": "dict", "keyType": { - "$id": "606", + "$id": "630", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, "valueType": { - "$id": "607", + "$id": "631", "kind": "nullable", "type": { - "$ref": "400" + "$ref": "416" }, "namespace": "SampleTypeSpec" }, @@ -8834,7 +9214,7 @@ "isExactName": false }, { - "$id": "608", + "$id": "632", "kind": "property", "name": "nestedChildren", "apiVersions": [ @@ -8843,24 +9223,24 @@ ], "serializedName": "nestedChildren", "type": { - "$id": "609", + "$id": "633", "kind": "nullable", "type": { - "$id": "610", + "$id": "634", "kind": "array", "name": "Array3", "valueType": { - "$id": "611", + "$id": "635", "kind": "nullable", "type": { - "$id": "612", + "$id": "636", "kind": "array", "name": "Array4", "valueType": { - "$id": "613", + "$id": "637", "kind": "nullable", "type": { - "$ref": "400" + "$ref": "416" }, "namespace": "SampleTypeSpec" }, @@ -8889,7 +9269,7 @@ "isExactName": false }, { - "$id": "614", + "$id": "638", "kind": "property", "name": "nestedChildDictionary", "apiVersions": [ @@ -8898,36 +9278,36 @@ ], "serializedName": "nestedChildDictionary", "type": { - "$id": "615", + "$id": "639", "kind": "nullable", "type": { - "$id": "616", + "$id": "640", "kind": "dict", "keyType": { - "$id": "617", + "$id": "641", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, "valueType": { - "$id": "618", + "$id": "642", "kind": "nullable", "type": { - "$id": "619", + "$id": "643", "kind": "dict", "keyType": { - "$id": "620", + "$id": "644", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, "valueType": { - "$id": "621", + "$id": "645", "kind": "nullable", "type": { - "$ref": "400" + "$ref": "416" }, "namespace": "SampleTypeSpec" }, @@ -8954,7 +9334,7 @@ "isExactName": false }, { - "$id": "622", + "$id": "646", "kind": "property", "name": "dictionaryChildren", "apiVersions": [ @@ -8963,30 +9343,30 @@ ], "serializedName": "dictionaryChildren", "type": { - "$id": "623", + "$id": "647", "kind": "nullable", "type": { - "$id": "624", + "$id": "648", "kind": "dict", "keyType": { - "$id": "625", + "$id": "649", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, "valueType": { - "$id": "626", + "$id": "650", "kind": "nullable", "type": { - "$id": "627", + "$id": "651", "kind": "array", "name": "Array5", "valueType": { - "$id": "628", + "$id": "652", "kind": "nullable", "type": { - "$ref": "400" + "$ref": "416" }, "namespace": "SampleTypeSpec" }, @@ -9014,7 +9394,7 @@ "isExactName": false }, { - "$id": "629", + "$id": "653", "kind": "property", "name": "listOfDictionaries", "apiVersions": [ @@ -9023,30 +9403,30 @@ ], "serializedName": "listOfDictionaries", "type": { - "$id": "630", + "$id": "654", "kind": "nullable", "type": { - "$id": "631", + "$id": "655", "kind": "array", "name": "Array6", "valueType": { - "$id": "632", + "$id": "656", "kind": "nullable", "type": { - "$id": "633", + "$id": "657", "kind": "dict", "keyType": { - "$id": "634", + "$id": "658", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", "decorators": [] }, "valueType": { - "$id": "635", + "$id": "659", "kind": "nullable", "type": { - "$ref": "400" + "$ref": "416" }, "namespace": "SampleTypeSpec" }, @@ -9076,7 +9456,7 @@ ] }, { - "$id": "636", + "$id": "660", "kind": "model", "name": "JsonlStreamStreamingItem", "apiVersions": [], @@ -9089,7 +9469,7 @@ "isExactName": false, "properties": [ { - "$id": "637", + "$id": "661", "kind": "property", "name": "contentType", "apiVersions": [ @@ -9097,7 +9477,7 @@ "2024-08-16-preview" ], "type": { - "$ref": "196" + "$ref": "204" }, "optional": false, "readOnly": false, @@ -9110,7 +9490,7 @@ "isExactName": false }, { - "$id": "638", + "$id": "662", "kind": "property", "name": "body", "apiVersions": [ @@ -9118,7 +9498,7 @@ "2024-08-16-preview" ], "type": { - "$id": "639", + "$id": "663", "kind": "bytes", "name": "bytes", "crossLanguageDefinitionId": "", @@ -9139,7 +9519,7 @@ ], "clients": [ { - "$id": "640", + "$id": "664", "kind": "client", "name": "SampleTypeSpecClient", "isExactName": false, @@ -9147,7 +9527,7 @@ "doc": "This is a sample typespec project.", "methods": [ { - "$id": "641", + "$id": "665", "kind": "basic", "name": "sayHi", "isExactName": false, @@ -9158,7 +9538,7 @@ ], "doc": "Return hi", "operation": { - "$id": "642", + "$id": "666", "name": "sayHi", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -9166,12 +9546,12 @@ "accessibility": "public", "parameters": [ { - "$id": "643", + "$id": "667", "kind": "header", "name": "headParameter", "serializedName": "head-parameter", "type": { - "$id": "644", + "$id": "668", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -9186,12 +9566,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.sayHi.headParameter", "methodParameterSegments": [ { - "$id": "645", + "$id": "669", "kind": "method", "name": "headParameter", "serializedName": "head-parameter", "type": { - "$id": "646", + "$id": "670", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -9211,12 +9591,12 @@ "isExactName": false }, { - "$id": "647", + "$id": "671", "kind": "query", "name": "queryParameter", "serializedName": "queryParameter", "type": { - "$id": "648", + "$id": "672", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -9231,12 +9611,12 @@ "readOnly": false, "methodParameterSegments": [ { - "$id": "649", + "$id": "673", "kind": "method", "name": "queryParameter", "serializedName": "queryParameter", "type": { - "$id": "650", + "$id": "674", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -9256,12 +9636,12 @@ "isExactName": false }, { - "$id": "651", + "$id": "675", "kind": "query", "name": "optionalQuery", "serializedName": "optionalQuery", "type": { - "$id": "652", + "$id": "676", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -9276,12 +9656,12 @@ "readOnly": false, "methodParameterSegments": [ { - "$id": "653", + "$id": "677", "kind": "method", "name": "optionalQuery", "serializedName": "optionalQuery", "type": { - "$id": "654", + "$id": "678", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -9301,12 +9681,12 @@ "isExactName": false }, { - "$id": "655", + "$id": "679", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "86" + "$ref": "94" }, "isApiVersion": false, "optional": false, @@ -9317,12 +9697,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.sayHi.accept", "methodParameterSegments": [ { - "$id": "656", + "$id": "680", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "86" + "$ref": "94" }, "location": "Header", "isApiVersion": false, @@ -9344,7 +9724,7 @@ 200 ], "bodyType": { - "$ref": "256" + "$ref": "272" }, "headers": [], "isErrorResponse": false, @@ -9370,21 +9750,21 @@ }, "parameters": [ { - "$ref": "645" + "$ref": "669" }, { - "$ref": "649" + "$ref": "673" }, { - "$ref": "653" + "$ref": "677" }, { - "$ref": "656" + "$ref": "680" } ], "response": { "type": { - "$ref": "256" + "$ref": "272" } }, "isOverride": false, @@ -9393,7 +9773,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.sayHi" }, { - "$id": "657", + "$id": "681", "kind": "basic", "name": "helloAgain", "isExactName": false, @@ -9404,7 +9784,7 @@ ], "doc": "Return hi again", "operation": { - "$id": "658", + "$id": "682", "name": "helloAgain", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -9412,12 +9792,12 @@ "accessibility": "public", "parameters": [ { - "$id": "659", + "$id": "683", "kind": "header", "name": "p1", "serializedName": "p1", "type": { - "$id": "660", + "$id": "684", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -9432,12 +9812,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.helloAgain.p1", "methodParameterSegments": [ { - "$id": "661", + "$id": "685", "kind": "method", "name": "p1", "serializedName": "p1", "type": { - "$id": "662", + "$id": "686", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -9457,12 +9837,12 @@ "isExactName": false }, { - "$id": "663", + "$id": "687", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "type": { - "$ref": "88" + "$ref": "96" }, "isApiVersion": false, "optional": false, @@ -9473,12 +9853,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.helloAgain.contentType", "methodParameterSegments": [ { - "$id": "664", + "$id": "688", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "type": { - "$ref": "88" + "$ref": "96" }, "location": "Header", "isApiVersion": false, @@ -9494,12 +9874,12 @@ "isExactName": false }, { - "$id": "665", + "$id": "689", "kind": "path", "name": "p2", "serializedName": "p2", "type": { - "$id": "666", + "$id": "690", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -9517,12 +9897,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.helloAgain.p2", "methodParameterSegments": [ { - "$id": "667", + "$id": "691", "kind": "method", "name": "p2", "serializedName": "p2", "type": { - "$id": "668", + "$id": "692", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -9542,12 +9922,12 @@ "isExactName": false }, { - "$id": "669", + "$id": "693", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "92" + "$ref": "100" }, "isApiVersion": false, "optional": false, @@ -9558,12 +9938,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.helloAgain.accept", "methodParameterSegments": [ { - "$id": "670", + "$id": "694", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "92" + "$ref": "100" }, "location": "Header", "isApiVersion": false, @@ -9579,12 +9959,12 @@ "isExactName": false }, { - "$id": "671", + "$id": "695", "kind": "body", "name": "action", "serializedName": "action", "type": { - "$ref": "291" + "$ref": "307" }, "isApiVersion": false, "contentTypes": [ @@ -9598,12 +9978,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.helloAgain.action", "methodParameterSegments": [ { - "$id": "672", + "$id": "696", "kind": "method", "name": "action", "serializedName": "action", "type": { - "$ref": "291" + "$ref": "307" }, "location": "Body", "isApiVersion": false, @@ -9626,7 +10006,7 @@ 200 ], "bodyType": { - "$ref": "291" + "$ref": "307" }, "headers": [], "isErrorResponse": false, @@ -9655,24 +10035,24 @@ }, "parameters": [ { - "$ref": "661" + "$ref": "685" }, { - "$ref": "672" + "$ref": "696" }, { - "$ref": "664" + "$ref": "688" }, { - "$ref": "667" + "$ref": "691" }, { - "$ref": "670" + "$ref": "694" } ], "response": { "type": { - "$ref": "291" + "$ref": "307" } }, "isOverride": false, @@ -9681,7 +10061,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.helloAgain" }, { - "$id": "673", + "$id": "697", "kind": "basic", "name": "noContentType", "isExactName": false, @@ -9692,7 +10072,7 @@ ], "doc": "Return hi again", "operation": { - "$id": "674", + "$id": "698", "name": "noContentType", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -9700,12 +10080,12 @@ "accessibility": "public", "parameters": [ { - "$id": "675", + "$id": "699", "kind": "header", "name": "p1", "serializedName": "p1", "type": { - "$id": "676", + "$id": "700", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -9720,12 +10100,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.noContentType.p1", "methodParameterSegments": [ { - "$id": "677", + "$id": "701", "kind": "method", "name": "info", "serializedName": "info", "type": { - "$ref": "339" + "$ref": "355" }, "location": "", "isApiVersion": false, @@ -9738,13 +10118,13 @@ "isExactName": false }, { - "$id": "678", + "$id": "702", "kind": "method", "name": "p1", "serializedName": "p1", "doc": "header parameter", "type": { - "$ref": "341" + "$ref": "357" }, "location": "", "isApiVersion": false, @@ -9760,12 +10140,12 @@ "isExactName": false }, { - "$id": "679", + "$id": "703", "kind": "path", "name": "p2", "serializedName": "p2", "type": { - "$id": "680", + "$id": "704", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -9783,16 +10163,16 @@ "crossLanguageDefinitionId": "SampleTypeSpec.noContentType.p2", "methodParameterSegments": [ { - "$ref": "677" + "$ref": "701" }, { - "$id": "681", + "$id": "705", "kind": "method", "name": "p2", "serializedName": "p2", "doc": "path parameter", "type": { - "$ref": "344" + "$ref": "360" }, "location": "", "isApiVersion": false, @@ -9808,13 +10188,13 @@ "isExactName": false }, { - "$id": "682", + "$id": "706", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "94" + "$ref": "102" }, "isApiVersion": false, "optional": false, @@ -9825,13 +10205,13 @@ "crossLanguageDefinitionId": "SampleTypeSpec.noContentType.contentType", "methodParameterSegments": [ { - "$id": "683", + "$id": "707", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "94" + "$ref": "102" }, "location": "Header", "isApiVersion": false, @@ -9847,12 +10227,12 @@ "isExactName": false }, { - "$id": "684", + "$id": "708", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "96" + "$ref": "104" }, "isApiVersion": false, "optional": false, @@ -9863,12 +10243,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.noContentType.accept", "methodParameterSegments": [ { - "$id": "685", + "$id": "709", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "96" + "$ref": "104" }, "location": "Header", "isApiVersion": false, @@ -9884,12 +10264,12 @@ "isExactName": false }, { - "$id": "686", + "$id": "710", "kind": "body", "name": "action", "serializedName": "action", "type": { - "$ref": "291" + "$ref": "307" }, "isApiVersion": false, "contentTypes": [ @@ -9903,16 +10283,16 @@ "crossLanguageDefinitionId": "SampleTypeSpec.noContentType.action", "methodParameterSegments": [ { - "$ref": "677" + "$ref": "701" }, { - "$id": "687", + "$id": "711", "kind": "method", "name": "action", "serializedName": "action", "doc": "body parameter", "type": { - "$ref": "291" + "$ref": "307" }, "location": "", "isApiVersion": false, @@ -9939,7 +10319,7 @@ 200 ], "bodyType": { - "$ref": "291" + "$ref": "307" }, "headers": [], "isErrorResponse": false, @@ -9968,18 +10348,18 @@ }, "parameters": [ { - "$ref": "677" + "$ref": "701" }, { - "$ref": "683" + "$ref": "707" }, { - "$ref": "685" + "$ref": "709" } ], "response": { "type": { - "$ref": "291" + "$ref": "307" } }, "isOverride": true, @@ -9988,7 +10368,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.noContentType" }, { - "$id": "688", + "$id": "712", "kind": "basic", "name": "helloDemo2", "isExactName": false, @@ -9999,7 +10379,7 @@ ], "doc": "Return hi in demo2", "operation": { - "$id": "689", + "$id": "713", "name": "helloDemo2", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -10007,12 +10387,12 @@ "accessibility": "public", "parameters": [ { - "$id": "690", + "$id": "714", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "98" + "$ref": "106" }, "isApiVersion": false, "optional": false, @@ -10023,12 +10403,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.helloDemo2.accept", "methodParameterSegments": [ { - "$id": "691", + "$id": "715", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "98" + "$ref": "106" }, "location": "Header", "isApiVersion": false, @@ -10050,7 +10430,7 @@ 200 ], "bodyType": { - "$ref": "256" + "$ref": "272" }, "headers": [], "isErrorResponse": false, @@ -10072,16 +10452,20 @@ "generateConvenienceMethod": true, "crossLanguageDefinitionId": "SampleTypeSpec.helloDemo2", "decorators": [], - "namespace": "SampleTypeSpec" + "namespace": "SampleTypeSpec", + "experimental": { + "diagnosticId": "SAMPLE0001", + "dependsOn": [] + } }, "parameters": [ { - "$ref": "691" + "$ref": "715" } ], "response": { "type": { - "$ref": "256" + "$ref": "272" } }, "isOverride": false, @@ -10090,7 +10474,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.helloDemo2" }, { - "$id": "692", + "$id": "716", "kind": "basic", "name": "createLiteral", "isExactName": false, @@ -10101,7 +10485,7 @@ ], "doc": "Create with literal value", "operation": { - "$id": "693", + "$id": "717", "name": "createLiteral", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -10109,13 +10493,13 @@ "accessibility": "public", "parameters": [ { - "$id": "694", + "$id": "718", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "100" + "$ref": "108" }, "isApiVersion": false, "optional": false, @@ -10126,13 +10510,13 @@ "crossLanguageDefinitionId": "SampleTypeSpec.createLiteral.contentType", "methodParameterSegments": [ { - "$id": "695", + "$id": "719", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "100" + "$ref": "108" }, "location": "Header", "isApiVersion": false, @@ -10148,12 +10532,12 @@ "isExactName": false }, { - "$id": "696", + "$id": "720", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "102" + "$ref": "110" }, "isApiVersion": false, "optional": false, @@ -10164,12 +10548,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.createLiteral.accept", "methodParameterSegments": [ { - "$id": "697", + "$id": "721", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "102" + "$ref": "110" }, "location": "Header", "isApiVersion": false, @@ -10185,12 +10569,12 @@ "isExactName": false }, { - "$id": "698", + "$id": "722", "kind": "body", "name": "body", "serializedName": "body", "type": { - "$ref": "256" + "$ref": "272" }, "isApiVersion": false, "contentTypes": [ @@ -10204,12 +10588,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.createLiteral.body", "methodParameterSegments": [ { - "$id": "699", + "$id": "723", "kind": "method", "name": "body", "serializedName": "body", "type": { - "$ref": "256" + "$ref": "272" }, "location": "Body", "isApiVersion": false, @@ -10236,7 +10620,7 @@ 200 ], "bodyType": { - "$ref": "256" + "$ref": "272" }, "headers": [], "isErrorResponse": false, @@ -10265,18 +10649,18 @@ }, "parameters": [ { - "$ref": "699" + "$ref": "723" }, { - "$ref": "695" + "$ref": "719" }, { - "$ref": "697" + "$ref": "721" } ], "response": { "type": { - "$ref": "256" + "$ref": "272" } }, "isOverride": false, @@ -10285,7 +10669,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.createLiteral" }, { - "$id": "700", + "$id": "724", "kind": "basic", "name": "helloLiteral", "isExactName": false, @@ -10296,7 +10680,7 @@ ], "doc": "Send literal parameters", "operation": { - "$id": "701", + "$id": "725", "name": "helloLiteral", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -10304,12 +10688,12 @@ "accessibility": "public", "parameters": [ { - "$id": "702", + "$id": "726", "kind": "header", "name": "p1", "serializedName": "p1", "type": { - "$ref": "104" + "$ref": "112" }, "isApiVersion": false, "optional": false, @@ -10320,12 +10704,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.helloLiteral.p1", "methodParameterSegments": [ { - "$id": "703", + "$id": "727", "kind": "method", "name": "p1", "serializedName": "p1", "type": { - "$ref": "106" + "$ref": "114" }, "location": "Header", "isApiVersion": false, @@ -10341,12 +10725,12 @@ "isExactName": false }, { - "$id": "704", + "$id": "728", "kind": "path", "name": "p2", "serializedName": "p2", "type": { - "$ref": "108" + "$ref": "116" }, "isApiVersion": false, "explode": false, @@ -10360,12 +10744,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.helloLiteral.p2", "methodParameterSegments": [ { - "$id": "705", + "$id": "729", "kind": "method", "name": "p2", "serializedName": "p2", "type": { - "$ref": "110" + "$ref": "118" }, "location": "Path", "isApiVersion": false, @@ -10381,12 +10765,12 @@ "isExactName": false }, { - "$id": "706", + "$id": "730", "kind": "query", "name": "p3", "serializedName": "p3", "type": { - "$ref": "112" + "$ref": "120" }, "isApiVersion": false, "explode": false, @@ -10397,12 +10781,12 @@ "readOnly": false, "methodParameterSegments": [ { - "$id": "707", + "$id": "731", "kind": "method", "name": "p3", "serializedName": "p3", "type": { - "$ref": "114" + "$ref": "122" }, "location": "Query", "isApiVersion": false, @@ -10418,12 +10802,12 @@ "isExactName": false }, { - "$id": "708", + "$id": "732", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "116" + "$ref": "124" }, "isApiVersion": false, "optional": false, @@ -10434,12 +10818,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.helloLiteral.accept", "methodParameterSegments": [ { - "$id": "709", + "$id": "733", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "116" + "$ref": "124" }, "location": "Header", "isApiVersion": false, @@ -10461,7 +10845,7 @@ 200 ], "bodyType": { - "$ref": "256" + "$ref": "272" }, "headers": [], "isErrorResponse": false, @@ -10487,21 +10871,21 @@ }, "parameters": [ { - "$ref": "703" + "$ref": "727" }, { - "$ref": "705" + "$ref": "729" }, { - "$ref": "707" + "$ref": "731" }, { - "$ref": "709" + "$ref": "733" } ], "response": { "type": { - "$ref": "256" + "$ref": "272" } }, "isOverride": false, @@ -10510,7 +10894,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.helloLiteral" }, { - "$id": "710", + "$id": "734", "kind": "basic", "name": "topAction", "isExactName": false, @@ -10521,7 +10905,7 @@ ], "doc": "top level method", "operation": { - "$id": "711", + "$id": "735", "name": "topAction", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -10529,17 +10913,17 @@ "accessibility": "public", "parameters": [ { - "$id": "712", + "$id": "736", "kind": "path", "name": "action", "serializedName": "action", "type": { - "$id": "713", + "$id": "737", "kind": "utcDateTime", "name": "utcDateTime", "encode": "rfc3339", "wireType": { - "$id": "714", + "$id": "738", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -10560,17 +10944,17 @@ "crossLanguageDefinitionId": "SampleTypeSpec.topAction.action", "methodParameterSegments": [ { - "$id": "715", + "$id": "739", "kind": "method", "name": "action", "serializedName": "action", "type": { - "$id": "716", + "$id": "740", "kind": "utcDateTime", "name": "utcDateTime", "encode": "rfc3339", "wireType": { - "$id": "717", + "$id": "741", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -10593,12 +10977,12 @@ "isExactName": false }, { - "$id": "718", + "$id": "742", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "118" + "$ref": "126" }, "isApiVersion": false, "optional": false, @@ -10609,12 +10993,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.topAction.accept", "methodParameterSegments": [ { - "$id": "719", + "$id": "743", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "118" + "$ref": "126" }, "location": "Header", "isApiVersion": false, @@ -10636,7 +11020,7 @@ 200 ], "bodyType": { - "$ref": "256" + "$ref": "272" }, "headers": [], "isErrorResponse": false, @@ -10662,15 +11046,15 @@ }, "parameters": [ { - "$ref": "715" + "$ref": "739" }, { - "$ref": "719" + "$ref": "743" } ], "response": { "type": { - "$ref": "256" + "$ref": "272" } }, "isOverride": false, @@ -10679,7 +11063,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.topAction" }, { - "$id": "720", + "$id": "744", "kind": "basic", "name": "topAction2", "isExactName": false, @@ -10690,7 +11074,7 @@ ], "doc": "top level method2", "operation": { - "$id": "721", + "$id": "745", "name": "topAction2", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -10698,12 +11082,12 @@ "accessibility": "public", "parameters": [ { - "$id": "722", + "$id": "746", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "120" + "$ref": "128" }, "isApiVersion": false, "optional": false, @@ -10714,12 +11098,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.topAction2.accept", "methodParameterSegments": [ { - "$id": "723", + "$id": "747", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "120" + "$ref": "128" }, "location": "Header", "isApiVersion": false, @@ -10741,7 +11125,7 @@ 200 ], "bodyType": { - "$ref": "256" + "$ref": "272" }, "headers": [], "isErrorResponse": false, @@ -10767,12 +11151,12 @@ }, "parameters": [ { - "$ref": "723" + "$ref": "747" } ], "response": { "type": { - "$ref": "256" + "$ref": "272" } }, "isOverride": false, @@ -10781,7 +11165,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.topAction2" }, { - "$id": "724", + "$id": "748", "kind": "basic", "name": "patchAction", "isExactName": false, @@ -10792,7 +11176,7 @@ ], "doc": "top level patch", "operation": { - "$id": "725", + "$id": "749", "name": "patchAction", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -10800,13 +11184,13 @@ "accessibility": "public", "parameters": [ { - "$id": "726", + "$id": "750", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "122" + "$ref": "130" }, "isApiVersion": false, "optional": false, @@ -10817,13 +11201,13 @@ "crossLanguageDefinitionId": "SampleTypeSpec.patchAction.contentType", "methodParameterSegments": [ { - "$id": "727", + "$id": "751", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "122" + "$ref": "130" }, "location": "Header", "isApiVersion": false, @@ -10839,12 +11223,12 @@ "isExactName": false }, { - "$id": "728", + "$id": "752", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "124" + "$ref": "132" }, "isApiVersion": false, "optional": false, @@ -10855,12 +11239,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.patchAction.accept", "methodParameterSegments": [ { - "$id": "729", + "$id": "753", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "124" + "$ref": "132" }, "location": "Header", "isApiVersion": false, @@ -10876,12 +11260,12 @@ "isExactName": false }, { - "$id": "730", + "$id": "754", "kind": "body", "name": "body", "serializedName": "body", "type": { - "$ref": "256" + "$ref": "272" }, "isApiVersion": false, "contentTypes": [ @@ -10895,12 +11279,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.patchAction.body", "methodParameterSegments": [ { - "$id": "731", + "$id": "755", "kind": "method", "name": "body", "serializedName": "body", "type": { - "$ref": "256" + "$ref": "272" }, "location": "Body", "isApiVersion": false, @@ -10927,7 +11311,7 @@ 200 ], "bodyType": { - "$ref": "256" + "$ref": "272" }, "headers": [], "isErrorResponse": false, @@ -10956,18 +11340,18 @@ }, "parameters": [ { - "$ref": "731" + "$ref": "755" }, { - "$ref": "727" + "$ref": "751" }, { - "$ref": "729" + "$ref": "753" } ], "response": { "type": { - "$ref": "256" + "$ref": "272" } }, "isOverride": false, @@ -10976,7 +11360,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.patchAction" }, { - "$id": "732", + "$id": "756", "kind": "basic", "name": "anonymousBody", "isExactName": false, @@ -10987,7 +11371,7 @@ ], "doc": "body parameter without body decorator", "operation": { - "$id": "733", + "$id": "757", "name": "anonymousBody", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -10995,12 +11379,12 @@ "accessibility": "public", "parameters": [ { - "$id": "734", + "$id": "758", "kind": "query", "name": "requiredQueryParam", "serializedName": "requiredQueryParam", "type": { - "$ref": "126" + "$ref": "134" }, "isApiVersion": false, "explode": false, @@ -11011,12 +11395,12 @@ "readOnly": false, "methodParameterSegments": [ { - "$id": "735", + "$id": "759", "kind": "method", "name": "requiredQueryParam", "serializedName": "requiredQueryParam", "type": { - "$ref": "128" + "$ref": "136" }, "location": "Query", "isApiVersion": false, @@ -11032,12 +11416,12 @@ "isExactName": false }, { - "$id": "736", + "$id": "760", "kind": "header", "name": "requiredHeader", "serializedName": "required-header", "type": { - "$ref": "130" + "$ref": "138" }, "isApiVersion": false, "optional": false, @@ -11048,12 +11432,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.anonymousBody.requiredHeader", "methodParameterSegments": [ { - "$id": "737", + "$id": "761", "kind": "method", "name": "requiredHeader", "serializedName": "required-header", "type": { - "$ref": "132" + "$ref": "140" }, "location": "Header", "isApiVersion": false, @@ -11069,13 +11453,13 @@ "isExactName": false }, { - "$id": "738", + "$id": "762", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "134" + "$ref": "142" }, "isApiVersion": false, "optional": false, @@ -11086,13 +11470,13 @@ "crossLanguageDefinitionId": "SampleTypeSpec.anonymousBody.contentType", "methodParameterSegments": [ { - "$id": "739", + "$id": "763", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "134" + "$ref": "142" }, "location": "Header", "isApiVersion": false, @@ -11108,12 +11492,12 @@ "isExactName": false }, { - "$id": "740", + "$id": "764", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "136" + "$ref": "144" }, "isApiVersion": false, "optional": false, @@ -11124,12 +11508,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.anonymousBody.accept", "methodParameterSegments": [ { - "$id": "741", + "$id": "765", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "136" + "$ref": "144" }, "location": "Header", "isApiVersion": false, @@ -11145,12 +11529,12 @@ "isExactName": false }, { - "$id": "742", + "$id": "766", "kind": "body", "name": "thing", "serializedName": "thing", "type": { - "$ref": "256" + "$ref": "272" }, "isApiVersion": false, "contentTypes": [ @@ -11164,13 +11548,13 @@ "crossLanguageDefinitionId": "SampleTypeSpec.anonymousBody.body", "methodParameterSegments": [ { - "$id": "743", + "$id": "767", "kind": "method", "name": "name", "serializedName": "name", "doc": "name of the Thing", "type": { - "$id": "744", + "$id": "768", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -11201,7 +11585,7 @@ 200 ], "bodyType": { - "$ref": "256" + "$ref": "272" }, "headers": [], "isErrorResponse": false, @@ -11230,16 +11614,16 @@ }, "parameters": [ { - "$ref": "743" + "$ref": "767" }, { - "$id": "745", + "$id": "769", "kind": "method", "name": "requiredUnion", "serializedName": "requiredUnion", "doc": "required Union", "type": { - "$ref": "260" + "$ref": "276" }, "location": "Body", "isApiVersion": false, @@ -11252,13 +11636,13 @@ "isExactName": false }, { - "$id": "746", + "$id": "770", "kind": "method", "name": "requiredLiteralString", "serializedName": "requiredLiteralString", "doc": "required literal string", "type": { - "$ref": "70" + "$ref": "78" }, "location": "Body", "isApiVersion": false, @@ -11271,13 +11655,13 @@ "isExactName": false }, { - "$id": "747", + "$id": "771", "kind": "method", "name": "requiredNullableString", "serializedName": "requiredNullableString", "doc": "required nullable string", "type": { - "$ref": "267" + "$ref": "283" }, "location": "Body", "isApiVersion": false, @@ -11290,13 +11674,13 @@ "isExactName": false }, { - "$id": "748", + "$id": "772", "kind": "method", "name": "optionalNullableString", "serializedName": "optionalNullableString", "doc": "required optional string", "type": { - "$ref": "270" + "$ref": "286" }, "location": "Body", "isApiVersion": false, @@ -11309,13 +11693,13 @@ "isExactName": false }, { - "$id": "749", + "$id": "773", "kind": "method", "name": "requiredLiteralInt", "serializedName": "requiredLiteralInt", "doc": "required literal int", "type": { - "$ref": "72" + "$ref": "80" }, "location": "Body", "isApiVersion": false, @@ -11328,13 +11712,13 @@ "isExactName": false }, { - "$id": "750", + "$id": "774", "kind": "method", "name": "requiredLiteralFloat", "serializedName": "requiredLiteralFloat", "doc": "required literal float", "type": { - "$ref": "74" + "$ref": "82" }, "location": "Body", "isApiVersion": false, @@ -11347,13 +11731,13 @@ "isExactName": false }, { - "$id": "751", + "$id": "775", "kind": "method", "name": "requiredLiteralBool", "serializedName": "requiredLiteralBool", "doc": "required literal bool", "type": { - "$ref": "76" + "$ref": "84" }, "location": "Body", "isApiVersion": false, @@ -11366,19 +11750,19 @@ "isExactName": false }, { - "$id": "752", + "$id": "776", "kind": "method", "name": "optionalLiteralString", "serializedName": "optionalLiteralString", "doc": "optional literal string", "type": { - "$id": "753", + "$id": "777", "kind": "enum", "name": "ThingOptionalLiteralString", "apiVersions": [], "crossLanguageDefinitionId": "", "valueType": { - "$id": "754", + "$id": "778", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -11386,12 +11770,12 @@ }, "values": [ { - "$id": "755", + "$id": "779", "kind": "enumvalue", "name": "reject", "value": "reject", "valueType": { - "$id": "756", + "$id": "780", "kind": "string", "decorators": [], "doc": "A sequence of textual characters.", @@ -11399,7 +11783,7 @@ "crossLanguageDefinitionId": "TypeSpec.string" }, "enumType": { - "$ref": "753" + "$ref": "777" }, "decorators": [], "isExactName": false @@ -11423,13 +11807,13 @@ "isExactName": false }, { - "$id": "757", + "$id": "781", "kind": "method", "name": "requiredNullableLiteralString", "serializedName": "requiredNullableLiteralString", "doc": "required nullable literal string", "type": { - "$ref": "277" + "$ref": "293" }, "location": "Body", "isApiVersion": false, @@ -11442,19 +11826,19 @@ "isExactName": false }, { - "$id": "758", + "$id": "782", "kind": "method", "name": "optionalLiteralInt", "serializedName": "optionalLiteralInt", "doc": "optional literal int", "type": { - "$id": "759", + "$id": "783", "kind": "enum", "name": "ThingOptionalLiteralInt", "apiVersions": [], "crossLanguageDefinitionId": "", "valueType": { - "$id": "760", + "$id": "784", "kind": "int32", "name": "int32", "crossLanguageDefinitionId": "TypeSpec.int32", @@ -11462,12 +11846,12 @@ }, "values": [ { - "$id": "761", + "$id": "785", "kind": "enumvalue", "name": "456", "value": 456, "valueType": { - "$id": "762", + "$id": "786", "kind": "int32", "decorators": [], "doc": "A 32-bit integer. (`-2,147,483,648` to `2,147,483,647`)", @@ -11475,7 +11859,7 @@ "crossLanguageDefinitionId": "TypeSpec.int32" }, "enumType": { - "$ref": "759" + "$ref": "783" }, "decorators": [], "isExactName": false @@ -11499,19 +11883,19 @@ "isExactName": false }, { - "$id": "763", + "$id": "787", "kind": "method", "name": "optionalLiteralFloat", "serializedName": "optionalLiteralFloat", "doc": "optional literal float", "type": { - "$id": "764", + "$id": "788", "kind": "enum", "name": "ThingOptionalLiteralFloat", "apiVersions": [], "crossLanguageDefinitionId": "", "valueType": { - "$id": "765", + "$id": "789", "kind": "float32", "name": "float32", "crossLanguageDefinitionId": "TypeSpec.float32", @@ -11519,12 +11903,12 @@ }, "values": [ { - "$id": "766", + "$id": "790", "kind": "enumvalue", "name": "4.56", "value": 4.56, "valueType": { - "$id": "767", + "$id": "791", "kind": "float32", "decorators": [], "doc": "A 32 bit floating point number. (`±1.5 x 10^−45` to `±3.4 x 10^38`)", @@ -11532,7 +11916,7 @@ "crossLanguageDefinitionId": "TypeSpec.float32" }, "enumType": { - "$ref": "764" + "$ref": "788" }, "decorators": [], "isExactName": false @@ -11556,13 +11940,13 @@ "isExactName": false }, { - "$id": "768", + "$id": "792", "kind": "method", "name": "optionalLiteralBool", "serializedName": "optionalLiteralBool", "doc": "optional literal bool", "type": { - "$ref": "78" + "$ref": "86" }, "location": "Body", "isApiVersion": false, @@ -11575,13 +11959,13 @@ "isExactName": false }, { - "$id": "769", + "$id": "793", "kind": "method", "name": "requiredBadDescription", "serializedName": "requiredBadDescription", "doc": "description with xml <|endoftext|>", "type": { - "$id": "770", + "$id": "794", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -11598,13 +11982,13 @@ "isExactName": false }, { - "$id": "771", + "$id": "795", "kind": "method", "name": "optionalNullableList", "serializedName": "optionalNullableList", "doc": "optional nullable collection", "type": { - "$ref": "284" + "$ref": "300" }, "location": "Body", "isApiVersion": false, @@ -11617,13 +12001,13 @@ "isExactName": false }, { - "$id": "772", + "$id": "796", "kind": "method", "name": "requiredNullableList", "serializedName": "requiredNullableList", "doc": "required nullable collection", "type": { - "$ref": "288" + "$ref": "304" }, "location": "Body", "isApiVersion": false, @@ -11636,13 +12020,13 @@ "isExactName": false }, { - "$id": "773", + "$id": "797", "kind": "method", "name": "propertyWithSpecialDocs", "serializedName": "propertyWithSpecialDocs", "doc": "This tests:\n- Simple bullet point. This bullet point is going to be very long to test how text wrapping is handled in bullet points within documentation comments. It should properly indent the wrapped lines.\n- Another bullet point with **bold text**. This bullet point is also intentionally long to see how the formatting is preserved when the text wraps onto multiple lines in the generated documentation.\n- Third bullet point with *italic text*. Similar to the previous points, this one is extended to ensure that the wrapping and formatting are correctly applied in the output.\n- Complex bullet point with **bold** and *italic* combined. This bullet point combines both bold and italic formatting and is long enough to test the wrapping behavior in such cases.\n- **Bold bullet point**: A bullet point that is entirely bolded. This point is also made lengthy to observe how the bold formatting is maintained across wrapped lines.\n- *Italic bullet point*: A bullet point that is entirely italicized. This final point is extended to verify that italic formatting is correctly applied even when the text spans multiple lines.", "type": { - "$id": "774", + "$id": "798", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -11659,21 +12043,21 @@ "isExactName": false }, { - "$ref": "735" + "$ref": "759" }, { - "$ref": "737" + "$ref": "761" }, { - "$ref": "739" + "$ref": "763" }, { - "$ref": "741" + "$ref": "765" } ], "response": { "type": { - "$ref": "256" + "$ref": "272" } }, "isOverride": false, @@ -11682,7 +12066,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.anonymousBody" }, { - "$id": "775", + "$id": "799", "kind": "basic", "name": "friendlyModel", "isExactName": false, @@ -11693,7 +12077,7 @@ ], "doc": "Model can have its friendly name", "operation": { - "$id": "776", + "$id": "800", "name": "friendlyModel", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -11701,13 +12085,13 @@ "accessibility": "public", "parameters": [ { - "$id": "777", + "$id": "801", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "148" + "$ref": "156" }, "isApiVersion": false, "optional": false, @@ -11718,13 +12102,13 @@ "crossLanguageDefinitionId": "SampleTypeSpec.friendlyModel.contentType", "methodParameterSegments": [ { - "$id": "778", + "$id": "802", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "148" + "$ref": "156" }, "location": "Header", "isApiVersion": false, @@ -11740,12 +12124,12 @@ "isExactName": false }, { - "$id": "779", + "$id": "803", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "150" + "$ref": "158" }, "isApiVersion": false, "optional": false, @@ -11756,12 +12140,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.friendlyModel.accept", "methodParameterSegments": [ { - "$id": "780", + "$id": "804", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "150" + "$ref": "158" }, "location": "Header", "isApiVersion": false, @@ -11777,12 +12161,12 @@ "isExactName": false }, { - "$id": "781", + "$id": "805", "kind": "body", "name": "friend", "serializedName": "friend", "type": { - "$ref": "345" + "$ref": "361" }, "isApiVersion": false, "contentTypes": [ @@ -11796,13 +12180,13 @@ "crossLanguageDefinitionId": "SampleTypeSpec.friendlyModel.body", "methodParameterSegments": [ { - "$id": "782", + "$id": "806", "kind": "method", "name": "name", "serializedName": "name", "doc": "name of the NotFriend", "type": { - "$id": "783", + "$id": "807", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -11833,7 +12217,7 @@ 200 ], "bodyType": { - "$ref": "345" + "$ref": "361" }, "headers": [], "isErrorResponse": false, @@ -11862,18 +12246,18 @@ }, "parameters": [ { - "$ref": "782" + "$ref": "806" }, { - "$ref": "778" + "$ref": "802" }, { - "$ref": "780" + "$ref": "804" } ], "response": { "type": { - "$ref": "345" + "$ref": "361" } }, "isOverride": false, @@ -11882,7 +12266,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.friendlyModel" }, { - "$id": "784", + "$id": "808", "kind": "basic", "name": "addTimeHeader", "isExactName": false, @@ -11892,24 +12276,24 @@ "2024-08-16-preview" ], "operation": { - "$id": "785", + "$id": "809", "name": "addTimeHeader", "isExactName": false, "resourceName": "SampleTypeSpec", "accessibility": "public", "parameters": [ { - "$id": "786", + "$id": "810", "kind": "header", "name": "repeatabilityFirstSent", "serializedName": "Repeatability-First-Sent", "type": { - "$id": "787", + "$id": "811", "kind": "utcDateTime", "name": "utcDateTime", "encode": "rfc7231", "wireType": { - "$id": "788", + "$id": "812", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -11927,17 +12311,17 @@ "crossLanguageDefinitionId": "SampleTypeSpec.addTimeHeader.repeatabilityFirstSent", "methodParameterSegments": [ { - "$id": "789", + "$id": "813", "kind": "method", "name": "repeatabilityFirstSent", "serializedName": "Repeatability-First-Sent", "type": { - "$id": "790", + "$id": "814", "kind": "utcDateTime", "name": "utcDateTime", "encode": "rfc7231", "wireType": { - "$id": "791", + "$id": "815", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -11982,7 +12366,7 @@ }, "parameters": [ { - "$ref": "789" + "$ref": "813" } ], "response": {}, @@ -11992,7 +12376,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.addTimeHeader" }, { - "$id": "792", + "$id": "816", "kind": "basic", "name": "projectedNameModel", "isExactName": false, @@ -12003,7 +12387,7 @@ ], "doc": "Model can have its projected name", "operation": { - "$id": "793", + "$id": "817", "name": "projectedNameModel", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -12011,13 +12395,13 @@ "accessibility": "public", "parameters": [ { - "$id": "794", + "$id": "818", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "152" + "$ref": "160" }, "isApiVersion": false, "optional": false, @@ -12028,13 +12412,13 @@ "crossLanguageDefinitionId": "SampleTypeSpec.projectedNameModel.contentType", "methodParameterSegments": [ { - "$id": "795", + "$id": "819", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "152" + "$ref": "160" }, "location": "Header", "isApiVersion": false, @@ -12050,12 +12434,12 @@ "isExactName": false }, { - "$id": "796", + "$id": "820", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "154" + "$ref": "162" }, "isApiVersion": false, "optional": false, @@ -12066,12 +12450,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.projectedNameModel.accept", "methodParameterSegments": [ { - "$id": "797", + "$id": "821", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "154" + "$ref": "162" }, "location": "Header", "isApiVersion": false, @@ -12087,12 +12471,12 @@ "isExactName": false }, { - "$id": "798", + "$id": "822", "kind": "body", "name": "renamedModel", "serializedName": "renamedModel", "type": { - "$ref": "348" + "$ref": "364" }, "isApiVersion": false, "contentTypes": [ @@ -12106,13 +12490,13 @@ "crossLanguageDefinitionId": "SampleTypeSpec.projectedNameModel.body", "methodParameterSegments": [ { - "$id": "799", + "$id": "823", "kind": "method", "name": "otherName", "serializedName": "otherName", "doc": "name of the ModelWithClientName", "type": { - "$id": "800", + "$id": "824", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -12143,7 +12527,7 @@ 200 ], "bodyType": { - "$ref": "348" + "$ref": "364" }, "headers": [], "isErrorResponse": false, @@ -12172,18 +12556,18 @@ }, "parameters": [ { - "$ref": "799" + "$ref": "823" }, { - "$ref": "795" + "$ref": "819" }, { - "$ref": "797" + "$ref": "821" } ], "response": { "type": { - "$ref": "348" + "$ref": "364" } }, "isOverride": false, @@ -12192,7 +12576,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.projectedNameModel" }, { - "$id": "801", + "$id": "825", "kind": "basic", "name": "returnsAnonymousModel", "isExactName": false, @@ -12203,7 +12587,7 @@ ], "doc": "return anonymous model", "operation": { - "$id": "802", + "$id": "826", "name": "returnsAnonymousModel", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -12211,12 +12595,12 @@ "accessibility": "public", "parameters": [ { - "$id": "803", + "$id": "827", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "156" + "$ref": "164" }, "isApiVersion": false, "optional": false, @@ -12227,12 +12611,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.returnsAnonymousModel.accept", "methodParameterSegments": [ { - "$id": "804", + "$id": "828", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "156" + "$ref": "164" }, "location": "Header", "isApiVersion": false, @@ -12254,7 +12638,7 @@ 200 ], "bodyType": { - "$ref": "351" + "$ref": "367" }, "headers": [], "isErrorResponse": false, @@ -12280,12 +12664,12 @@ }, "parameters": [ { - "$ref": "804" + "$ref": "828" } ], "response": { "type": { - "$ref": "351" + "$ref": "367" } }, "isOverride": false, @@ -12294,7 +12678,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.returnsAnonymousModel" }, { - "$id": "805", + "$id": "829", "kind": "basic", "name": "getUnknownValue", "isExactName": false, @@ -12305,7 +12689,7 @@ ], "doc": "get extensible enum", "operation": { - "$id": "806", + "$id": "830", "name": "getUnknownValue", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -12313,12 +12697,12 @@ "accessibility": "public", "parameters": [ { - "$id": "807", + "$id": "831", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "158" + "$ref": "166" }, "isApiVersion": false, "optional": false, @@ -12329,12 +12713,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.getUnknownValue.accept", "methodParameterSegments": [ { - "$id": "808", + "$id": "832", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "158" + "$ref": "166" }, "location": "Header", "isApiVersion": false, @@ -12356,7 +12740,7 @@ 200 ], "bodyType": { - "$ref": "57" + "$ref": "65" }, "headers": [], "isErrorResponse": false, @@ -12378,12 +12762,12 @@ }, "parameters": [ { - "$ref": "808" + "$ref": "832" } ], "response": { "type": { - "$ref": "57" + "$ref": "65" } }, "isOverride": false, @@ -12392,7 +12776,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.getUnknownValue" }, { - "$id": "809", + "$id": "833", "kind": "basic", "name": "internalProtocol", "isExactName": false, @@ -12403,7 +12787,7 @@ ], "doc": "When set protocol false and convenient true, then the protocol method should be internal", "operation": { - "$id": "810", + "$id": "834", "name": "internalProtocol", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -12411,13 +12795,13 @@ "accessibility": "public", "parameters": [ { - "$id": "811", + "$id": "835", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "160" + "$ref": "168" }, "isApiVersion": false, "optional": false, @@ -12428,13 +12812,13 @@ "crossLanguageDefinitionId": "SampleTypeSpec.internalProtocol.contentType", "methodParameterSegments": [ { - "$id": "812", + "$id": "836", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "160" + "$ref": "168" }, "location": "Header", "isApiVersion": false, @@ -12450,12 +12834,12 @@ "isExactName": false }, { - "$id": "813", + "$id": "837", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "162" + "$ref": "170" }, "isApiVersion": false, "optional": false, @@ -12466,12 +12850,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.internalProtocol.accept", "methodParameterSegments": [ { - "$id": "814", + "$id": "838", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "162" + "$ref": "170" }, "location": "Header", "isApiVersion": false, @@ -12487,12 +12871,12 @@ "isExactName": false }, { - "$id": "815", + "$id": "839", "kind": "body", "name": "body", "serializedName": "body", "type": { - "$ref": "256" + "$ref": "272" }, "isApiVersion": false, "contentTypes": [ @@ -12506,12 +12890,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.internalProtocol.body", "methodParameterSegments": [ { - "$id": "816", + "$id": "840", "kind": "method", "name": "body", "serializedName": "body", "type": { - "$ref": "256" + "$ref": "272" }, "location": "Body", "isApiVersion": false, @@ -12538,7 +12922,7 @@ 200 ], "bodyType": { - "$ref": "256" + "$ref": "272" }, "headers": [], "isErrorResponse": false, @@ -12567,18 +12951,18 @@ }, "parameters": [ { - "$ref": "816" + "$ref": "840" }, { - "$ref": "812" + "$ref": "836" }, { - "$ref": "814" + "$ref": "838" } ], "response": { "type": { - "$ref": "256" + "$ref": "272" } }, "isOverride": false, @@ -12587,7 +12971,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.internalProtocol" }, { - "$id": "817", + "$id": "841", "kind": "basic", "name": "stillConvenient", "isExactName": false, @@ -12598,7 +12982,7 @@ ], "doc": "When set protocol false and convenient true, the convenient method should be generated even it has the same signature as protocol one", "operation": { - "$id": "818", + "$id": "842", "name": "stillConvenient", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -12633,7 +13017,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.stillConvenient" }, { - "$id": "819", + "$id": "843", "kind": "basic", "name": "headAsBoolean", "isExactName": false, @@ -12644,7 +13028,7 @@ ], "doc": "head as boolean.", "operation": { - "$id": "820", + "$id": "844", "name": "headAsBoolean", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -12652,12 +13036,12 @@ "accessibility": "public", "parameters": [ { - "$id": "821", + "$id": "845", "kind": "path", "name": "id", "serializedName": "id", "type": { - "$id": "822", + "$id": "846", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -12675,12 +13059,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.headAsBoolean.id", "methodParameterSegments": [ { - "$id": "823", + "$id": "847", "kind": "method", "name": "id", "serializedName": "id", "type": { - "$id": "824", + "$id": "848", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -12722,7 +13106,7 @@ }, "parameters": [ { - "$ref": "823" + "$ref": "847" } ], "response": {}, @@ -12732,7 +13116,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.headAsBoolean" }, { - "$id": "825", + "$id": "849", "kind": "basic", "name": "WithApiVersion", "isExactName": false, @@ -12743,7 +13127,7 @@ ], "doc": "Return hi again", "operation": { - "$id": "826", + "$id": "850", "name": "WithApiVersion", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -12751,12 +13135,12 @@ "accessibility": "public", "parameters": [ { - "$id": "827", + "$id": "851", "kind": "header", "name": "p1", "serializedName": "p1", "type": { - "$id": "828", + "$id": "852", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -12771,12 +13155,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.WithApiVersion.p1", "methodParameterSegments": [ { - "$id": "829", + "$id": "853", "kind": "method", "name": "p1", "serializedName": "p1", "type": { - "$id": "830", + "$id": "854", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -12796,12 +13180,12 @@ "isExactName": false }, { - "$id": "831", + "$id": "855", "kind": "query", "name": "apiVersion", "serializedName": "apiVersion", "type": { - "$id": "832", + "$id": "856", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -12811,7 +13195,7 @@ "explode": false, "defaultValue": { "type": { - "$id": "833", + "$id": "857", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string" @@ -12825,12 +13209,12 @@ "readOnly": false, "methodParameterSegments": [ { - "$id": "834", + "$id": "858", "kind": "method", "name": "apiVersion", "serializedName": "apiVersion", "type": { - "$id": "835", + "$id": "859", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -12840,7 +13224,7 @@ "isApiVersion": true, "defaultValue": { "type": { - "$id": "836", + "$id": "860", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string" @@ -12881,7 +13265,7 @@ }, "parameters": [ { - "$ref": "829" + "$ref": "853" } ], "response": {}, @@ -12891,7 +13275,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.WithApiVersion" }, { - "$id": "837", + "$id": "861", "kind": "paging", "name": "ListWithNextLink", "isExactName": false, @@ -12902,7 +13286,7 @@ ], "doc": "List things with nextlink", "operation": { - "$id": "838", + "$id": "862", "name": "ListWithNextLink", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -12910,12 +13294,12 @@ "accessibility": "public", "parameters": [ { - "$id": "839", + "$id": "863", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "164" + "$ref": "172" }, "isApiVersion": false, "optional": false, @@ -12926,12 +13310,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.ListWithNextLink.accept", "methodParameterSegments": [ { - "$id": "840", + "$id": "864", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "164" + "$ref": "172" }, "location": "Header", "isApiVersion": false, @@ -12953,7 +13337,7 @@ 200 ], "bodyType": { - "$ref": "352" + "$ref": "368" }, "headers": [], "isErrorResponse": false, @@ -12979,12 +13363,12 @@ }, "parameters": [ { - "$ref": "840" + "$ref": "864" } ], "response": { "type": { - "$ref": "354" + "$ref": "370" }, "resultSegments": [ "things" @@ -13009,7 +13393,7 @@ } }, { - "$id": "841", + "$id": "865", "kind": "paging", "name": "ListWithStringNextLink", "isExactName": false, @@ -13020,7 +13404,7 @@ ], "doc": "List things with nextlink", "operation": { - "$id": "842", + "$id": "866", "name": "ListWithStringNextLink", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -13028,12 +13412,12 @@ "accessibility": "public", "parameters": [ { - "$id": "843", + "$id": "867", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "166" + "$ref": "174" }, "isApiVersion": false, "optional": false, @@ -13044,12 +13428,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.ListWithStringNextLink.accept", "methodParameterSegments": [ { - "$id": "844", + "$id": "868", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "166" + "$ref": "174" }, "location": "Header", "isApiVersion": false, @@ -13071,7 +13455,7 @@ 200 ], "bodyType": { - "$ref": "357" + "$ref": "373" }, "headers": [], "isErrorResponse": false, @@ -13097,12 +13481,12 @@ }, "parameters": [ { - "$ref": "844" + "$ref": "868" } ], "response": { "type": { - "$ref": "354" + "$ref": "370" }, "resultSegments": [ "things" @@ -13127,7 +13511,7 @@ } }, { - "$id": "845", + "$id": "869", "kind": "paging", "name": "ListWithContinuationToken", "isExactName": false, @@ -13138,7 +13522,7 @@ ], "doc": "List things with continuation token", "operation": { - "$id": "846", + "$id": "870", "name": "ListWithContinuationToken", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -13146,12 +13530,12 @@ "accessibility": "public", "parameters": [ { - "$id": "847", + "$id": "871", "kind": "query", "name": "token", "serializedName": "token", "type": { - "$id": "848", + "$id": "872", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -13166,12 +13550,12 @@ "readOnly": false, "methodParameterSegments": [ { - "$id": "849", + "$id": "873", "kind": "method", "name": "token", "serializedName": "token", "type": { - "$id": "850", + "$id": "874", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -13191,12 +13575,12 @@ "isExactName": false }, { - "$id": "851", + "$id": "875", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "168" + "$ref": "176" }, "isApiVersion": false, "optional": false, @@ -13207,12 +13591,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.ListWithContinuationToken.accept", "methodParameterSegments": [ { - "$id": "852", + "$id": "876", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "168" + "$ref": "176" }, "location": "Header", "isApiVersion": false, @@ -13234,7 +13618,7 @@ 200 ], "bodyType": { - "$ref": "361" + "$ref": "377" }, "headers": [], "isErrorResponse": false, @@ -13260,15 +13644,15 @@ }, "parameters": [ { - "$ref": "849" + "$ref": "873" }, { - "$ref": "852" + "$ref": "876" } ], "response": { "type": { - "$ref": "354" + "$ref": "370" }, "resultSegments": [ "things" @@ -13284,7 +13668,7 @@ ], "continuationToken": { "parameter": { - "$ref": "847" + "$ref": "871" }, "responseSegments": [ "nextToken" @@ -13295,7 +13679,7 @@ } }, { - "$id": "853", + "$id": "877", "kind": "paging", "name": "ListWithContinuationTokenHeaderResponse", "isExactName": false, @@ -13306,7 +13690,7 @@ ], "doc": "List things with continuation token header response", "operation": { - "$id": "854", + "$id": "878", "name": "ListWithContinuationTokenHeaderResponse", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -13314,12 +13698,12 @@ "accessibility": "public", "parameters": [ { - "$id": "855", + "$id": "879", "kind": "query", "name": "token", "serializedName": "token", "type": { - "$id": "856", + "$id": "880", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -13334,12 +13718,12 @@ "readOnly": false, "methodParameterSegments": [ { - "$id": "857", + "$id": "881", "kind": "method", "name": "token", "serializedName": "token", "type": { - "$id": "858", + "$id": "882", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -13359,12 +13743,12 @@ "isExactName": false }, { - "$id": "859", + "$id": "883", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "170" + "$ref": "178" }, "isApiVersion": false, "optional": false, @@ -13375,12 +13759,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.ListWithContinuationTokenHeaderResponse.accept", "methodParameterSegments": [ { - "$id": "860", + "$id": "884", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "170" + "$ref": "178" }, "location": "Header", "isApiVersion": false, @@ -13402,14 +13786,14 @@ 200 ], "bodyType": { - "$ref": "365" + "$ref": "381" }, "headers": [ { "name": "nextToken", "nameInResponse": "next-token", "type": { - "$id": "861", + "$id": "885", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -13440,15 +13824,15 @@ }, "parameters": [ { - "$ref": "857" + "$ref": "881" }, { - "$ref": "860" + "$ref": "884" } ], "response": { "type": { - "$ref": "354" + "$ref": "370" }, "resultSegments": [ "things" @@ -13464,7 +13848,7 @@ ], "continuationToken": { "parameter": { - "$ref": "855" + "$ref": "879" }, "responseSegments": [ "next-token" @@ -13475,7 +13859,7 @@ } }, { - "$id": "862", + "$id": "886", "kind": "paging", "name": "ListWithPaging", "isExactName": false, @@ -13486,7 +13870,7 @@ ], "doc": "List things with paging", "operation": { - "$id": "863", + "$id": "887", "name": "ListWithPaging", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -13494,12 +13878,12 @@ "accessibility": "public", "parameters": [ { - "$id": "864", + "$id": "888", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "172" + "$ref": "180" }, "isApiVersion": false, "optional": false, @@ -13510,12 +13894,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.ListWithPaging.accept", "methodParameterSegments": [ { - "$id": "865", + "$id": "889", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "172" + "$ref": "180" }, "location": "Header", "isApiVersion": false, @@ -13537,7 +13921,7 @@ 200 ], "bodyType": { - "$ref": "367" + "$ref": "383" }, "headers": [], "isErrorResponse": false, @@ -13563,12 +13947,12 @@ }, "parameters": [ { - "$ref": "865" + "$ref": "889" } ], "response": { "type": { - "$ref": "354" + "$ref": "370" }, "resultSegments": [ "items" @@ -13586,7 +13970,7 @@ } }, { - "$id": "866", + "$id": "890", "kind": "basic", "name": "EmbeddedParameters", "isExactName": false, @@ -13597,7 +13981,7 @@ ], "doc": "An operation with embedded parameters within the body", "operation": { - "$id": "867", + "$id": "891", "name": "EmbeddedParameters", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -13605,13 +13989,13 @@ "accessibility": "public", "parameters": [ { - "$id": "868", + "$id": "892", "kind": "header", "name": "requiredHeader", "serializedName": "required-header", "doc": "required header parameter", "type": { - "$id": "869", + "$id": "893", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -13626,12 +14010,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.ModelWithEmbeddedNonBodyParameters.requiredHeader", "methodParameterSegments": [ { - "$id": "870", + "$id": "894", "kind": "method", "name": "body", "serializedName": "body", "type": { - "$ref": "369" + "$ref": "385" }, "location": "Body", "isApiVersion": false, @@ -13644,13 +14028,13 @@ "isExactName": false }, { - "$id": "871", + "$id": "895", "kind": "method", "name": "requiredHeader", "serializedName": "requiredHeader", "doc": "required header parameter", "type": { - "$ref": "373" + "$ref": "389" }, "location": "", "isApiVersion": false, @@ -13666,13 +14050,13 @@ "isExactName": false }, { - "$id": "872", + "$id": "896", "kind": "header", "name": "optionalHeader", "serializedName": "optional-header", "doc": "optional header parameter", "type": { - "$id": "873", + "$id": "897", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -13687,16 +14071,16 @@ "crossLanguageDefinitionId": "SampleTypeSpec.ModelWithEmbeddedNonBodyParameters.optionalHeader", "methodParameterSegments": [ { - "$ref": "870" + "$ref": "894" }, { - "$id": "874", + "$id": "898", "kind": "method", "name": "optionalHeader", "serializedName": "optionalHeader", "doc": "optional header parameter", "type": { - "$ref": "375" + "$ref": "391" }, "location": "", "isApiVersion": false, @@ -13712,13 +14096,13 @@ "isExactName": false }, { - "$id": "875", + "$id": "899", "kind": "query", "name": "requiredQuery", "serializedName": "requiredQuery", "doc": "required query parameter", "type": { - "$id": "876", + "$id": "900", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -13733,16 +14117,16 @@ "readOnly": false, "methodParameterSegments": [ { - "$ref": "870" + "$ref": "894" }, { - "$id": "877", + "$id": "901", "kind": "method", "name": "requiredQuery", "serializedName": "requiredQuery", "doc": "required query parameter", "type": { - "$ref": "377" + "$ref": "393" }, "location": "", "isApiVersion": false, @@ -13758,13 +14142,13 @@ "isExactName": false }, { - "$id": "878", + "$id": "902", "kind": "query", "name": "optionalQuery", "serializedName": "optionalQuery", "doc": "optional query parameter", "type": { - "$id": "879", + "$id": "903", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -13779,16 +14163,16 @@ "readOnly": false, "methodParameterSegments": [ { - "$ref": "870" + "$ref": "894" }, { - "$id": "880", + "$id": "904", "kind": "method", "name": "optionalQuery", "serializedName": "optionalQuery", "doc": "optional query parameter", "type": { - "$ref": "379" + "$ref": "395" }, "location": "", "isApiVersion": false, @@ -13804,13 +14188,13 @@ "isExactName": false }, { - "$id": "881", + "$id": "905", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "174" + "$ref": "182" }, "isApiVersion": false, "optional": false, @@ -13821,13 +14205,13 @@ "crossLanguageDefinitionId": "SampleTypeSpec.EmbeddedParameters.contentType", "methodParameterSegments": [ { - "$id": "882", + "$id": "906", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "174" + "$ref": "182" }, "location": "Header", "isApiVersion": false, @@ -13843,12 +14227,12 @@ "isExactName": false }, { - "$id": "883", + "$id": "907", "kind": "body", "name": "body", "serializedName": "body", "type": { - "$ref": "369" + "$ref": "385" }, "isApiVersion": false, "contentTypes": [ @@ -13862,7 +14246,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.EmbeddedParameters.body", "methodParameterSegments": [ { - "$ref": "870" + "$ref": "894" } ], "isExactName": false, @@ -13898,10 +14282,10 @@ }, "parameters": [ { - "$ref": "870" + "$ref": "894" }, { - "$ref": "882" + "$ref": "906" } ], "response": {}, @@ -13911,7 +14295,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.EmbeddedParameters" }, { - "$id": "884", + "$id": "908", "kind": "basic", "name": "DynamicModelOperation", "isExactName": false, @@ -13922,7 +14306,7 @@ ], "doc": "An operation with a dynamic model", "operation": { - "$id": "885", + "$id": "909", "name": "DynamicModelOperation", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -13930,13 +14314,13 @@ "accessibility": "public", "parameters": [ { - "$id": "886", + "$id": "910", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "176" + "$ref": "184" }, "isApiVersion": false, "optional": false, @@ -13947,13 +14331,13 @@ "crossLanguageDefinitionId": "SampleTypeSpec.DynamicModelOperation.contentType", "methodParameterSegments": [ { - "$id": "887", + "$id": "911", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "176" + "$ref": "184" }, "location": "Header", "isApiVersion": false, @@ -13969,12 +14353,12 @@ "isExactName": false }, { - "$id": "888", + "$id": "912", "kind": "body", "name": "body", "serializedName": "body", "type": { - "$ref": "380" + "$ref": "396" }, "isApiVersion": false, "contentTypes": [ @@ -13988,12 +14372,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.DynamicModelOperation.body", "methodParameterSegments": [ { - "$id": "889", + "$id": "913", "kind": "method", "name": "body", "serializedName": "body", "type": { - "$ref": "380" + "$ref": "396" }, "location": "Body", "isApiVersion": false, @@ -14035,14 +14419,20 @@ "generateConvenienceMethod": true, "crossLanguageDefinitionId": "SampleTypeSpec.DynamicModelOperation", "decorators": [], - "namespace": "SampleTypeSpec" + "namespace": "SampleTypeSpec", + "experimental": { + "diagnosticId": "SAMPLE0002", + "dependsOn": [ + "SCME0001" + ] + } }, "parameters": [ { - "$ref": "889" + "$ref": "913" }, { - "$ref": "887" + "$ref": "911" } ], "response": {}, @@ -14052,7 +14442,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.DynamicModelOperation" }, { - "$id": "890", + "$id": "914", "kind": "basic", "name": "GetXmlAdvancedModel", "isExactName": false, @@ -14063,7 +14453,7 @@ ], "doc": "Get an advanced XML model with various property types", "operation": { - "$id": "891", + "$id": "915", "name": "GetXmlAdvancedModel", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -14071,12 +14461,12 @@ "accessibility": "public", "parameters": [ { - "$id": "892", + "$id": "916", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "178" + "$ref": "186" }, "isApiVersion": false, "optional": false, @@ -14087,12 +14477,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.GetXmlAdvancedModel.accept", "methodParameterSegments": [ { - "$id": "893", + "$id": "917", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "178" + "$ref": "186" }, "location": "Header", "isApiVersion": false, @@ -14114,14 +14504,14 @@ 200 ], "bodyType": { - "$ref": "418" + "$ref": "434" }, "headers": [ { "name": "contentType", "nameInResponse": "content-type", "type": { - "$ref": "180" + "$ref": "188" } } ], @@ -14148,12 +14538,12 @@ }, "parameters": [ { - "$ref": "893" + "$ref": "917" } ], "response": { "type": { - "$ref": "418" + "$ref": "434" } }, "isOverride": false, @@ -14162,7 +14552,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.GetXmlAdvancedModel" }, { - "$id": "894", + "$id": "918", "kind": "basic", "name": "UpdateXmlAdvancedModel", "isExactName": false, @@ -14173,7 +14563,7 @@ ], "doc": "Update an advanced XML model with various property types", "operation": { - "$id": "895", + "$id": "919", "name": "UpdateXmlAdvancedModel", "isExactName": false, "resourceName": "SampleTypeSpec", @@ -14181,12 +14571,12 @@ "accessibility": "public", "parameters": [ { - "$id": "896", + "$id": "920", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "type": { - "$ref": "182" + "$ref": "190" }, "isApiVersion": false, "optional": false, @@ -14197,12 +14587,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.UpdateXmlAdvancedModel.contentType", "methodParameterSegments": [ { - "$id": "897", + "$id": "921", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "type": { - "$ref": "182" + "$ref": "190" }, "location": "Header", "isApiVersion": false, @@ -14218,12 +14608,12 @@ "isExactName": false }, { - "$id": "898", + "$id": "922", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "186" + "$ref": "194" }, "isApiVersion": false, "optional": false, @@ -14234,12 +14624,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.UpdateXmlAdvancedModel.accept", "methodParameterSegments": [ { - "$id": "899", + "$id": "923", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "186" + "$ref": "194" }, "location": "Header", "isApiVersion": false, @@ -14255,12 +14645,12 @@ "isExactName": false }, { - "$id": "900", + "$id": "924", "kind": "body", "name": "body", "serializedName": "body", "type": { - "$ref": "418" + "$ref": "434" }, "isApiVersion": false, "contentTypes": [ @@ -14274,12 +14664,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.UpdateXmlAdvancedModel.body", "methodParameterSegments": [ { - "$id": "901", + "$id": "925", "kind": "method", "name": "body", "serializedName": "body", "type": { - "$ref": "418" + "$ref": "434" }, "location": "Body", "isApiVersion": false, @@ -14306,14 +14696,14 @@ 200 ], "bodyType": { - "$ref": "418" + "$ref": "434" }, "headers": [ { "name": "contentType", "nameInResponse": "content-type", "type": { - "$ref": "188" + "$ref": "196" } } ], @@ -14343,18 +14733,18 @@ }, "parameters": [ { - "$ref": "901" + "$ref": "925" }, { - "$ref": "897" + "$ref": "921" }, { - "$ref": "899" + "$ref": "923" } ], "response": { "type": { - "$ref": "418" + "$ref": "434" } }, "isOverride": false, @@ -14363,7 +14753,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.UpdateXmlAdvancedModel" }, { - "$id": "902", + "$id": "926", "kind": "basic", "name": "uploadCat", "isExactName": false, @@ -14373,19 +14763,19 @@ "2024-08-16-preview" ], "operation": { - "$id": "903", + "$id": "927", "name": "uploadCat", "isExactName": false, "resourceName": "SampleTypeSpec", "accessibility": "public", "parameters": [ { - "$id": "904", + "$id": "928", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "type": { - "$ref": "190" + "$ref": "198" }, "isApiVersion": false, "optional": false, @@ -14396,12 +14786,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.uploadCat.contentType", "methodParameterSegments": [ { - "$id": "905", + "$id": "929", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "type": { - "$ref": "190" + "$ref": "198" }, "location": "Header", "isApiVersion": false, @@ -14417,12 +14807,12 @@ "isExactName": false }, { - "$id": "906", + "$id": "930", "kind": "body", "name": "body", "serializedName": "body", "type": { - "$ref": "514" + "$ref": "530" }, "isApiVersion": false, "contentTypes": [ @@ -14436,12 +14826,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.uploadCat.body", "methodParameterSegments": [ { - "$id": "907", + "$id": "931", "kind": "method", "name": "body", "serializedName": "body", "type": { - "$ref": "514" + "$ref": "530" }, "location": "Body", "isApiVersion": false, @@ -14483,10 +14873,10 @@ }, "parameters": [ { - "$ref": "905" + "$ref": "929" }, { - "$ref": "907" + "$ref": "931" } ], "response": {}, @@ -14496,7 +14886,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.uploadCat" }, { - "$id": "908", + "$id": "932", "kind": "basic", "name": "sendJsonLines", "isExactName": false, @@ -14506,19 +14896,19 @@ "2024-08-16-preview" ], "operation": { - "$id": "909", + "$id": "933", "name": "sendJsonLines", "isExactName": false, "resourceName": "SampleTypeSpec", "accessibility": "public", "parameters": [ { - "$id": "910", + "$id": "934", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "type": { - "$ref": "194" + "$ref": "202" }, "isApiVersion": false, "optional": false, @@ -14529,16 +14919,16 @@ "crossLanguageDefinitionId": "TypeSpec.Http.Streams.JsonlStream.contentType", "methodParameterSegments": [ { - "$id": "911", + "$id": "935", "kind": "method", "name": "stream", "serializedName": "stream", "type": { - "$id": "912", + "$id": "936", "kind": "streaming", "name": "JsonlStreamStreamingItem", "valueType": { - "$ref": "559" + "$ref": "575" }, "streamKind": "jsonl", "contentTypes": [ @@ -14557,12 +14947,12 @@ "isExactName": false }, { - "$id": "913", + "$id": "937", "kind": "method", "name": "contentType", "serializedName": "contentType", "type": { - "$ref": "196" + "$ref": "204" }, "location": "", "isApiVersion": false, @@ -14578,16 +14968,16 @@ "isExactName": false }, { - "$id": "914", + "$id": "938", "kind": "body", "name": "body", "serializedName": "body", "type": { - "$id": "915", + "$id": "939", "kind": "streaming", "name": "JsonlStreamStreamingItem", "valueType": { - "$ref": "559" + "$ref": "575" }, "streamKind": "jsonl", "contentTypes": [ @@ -14607,15 +14997,15 @@ "crossLanguageDefinitionId": "TypeSpec.Http.Streams.JsonlStream.body", "methodParameterSegments": [ { - "$ref": "911" + "$ref": "935" }, { - "$id": "916", + "$id": "940", "kind": "method", "name": "body", "serializedName": "body", "type": { - "$ref": "639" + "$ref": "663" }, "location": "", "isApiVersion": false, @@ -14661,7 +15051,7 @@ }, "parameters": [ { - "$ref": "911" + "$ref": "935" } ], "response": {}, @@ -14671,7 +15061,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.sendJsonLines" }, { - "$id": "917", + "$id": "941", "kind": "basic", "name": "receiveJsonLines", "isExactName": false, @@ -14681,19 +15071,19 @@ "2024-08-16-preview" ], "operation": { - "$id": "918", + "$id": "942", "name": "receiveJsonLines", "isExactName": false, "resourceName": "SampleTypeSpec", "accessibility": "public", "parameters": [ { - "$id": "919", + "$id": "943", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "198" + "$ref": "206" }, "isApiVersion": false, "optional": false, @@ -14704,12 +15094,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.receiveJsonLines.accept", "methodParameterSegments": [ { - "$id": "920", + "$id": "944", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "198" + "$ref": "206" }, "location": "Header", "isApiVersion": false, @@ -14731,11 +15121,11 @@ 200 ], "bodyType": { - "$id": "921", + "$id": "945", "kind": "streaming", "name": "JsonlStreamStreamingItem", "valueType": { - "$ref": "559" + "$ref": "575" }, "streamKind": "jsonl", "contentTypes": [ @@ -14748,7 +15138,7 @@ "name": "contentType", "nameInResponse": "content-type", "type": { - "$ref": "200" + "$ref": "208" } } ], @@ -14775,16 +15165,16 @@ }, "parameters": [ { - "$ref": "920" + "$ref": "944" } ], "response": { "type": { - "$id": "922", + "$id": "946", "kind": "streaming", "name": "JsonlStreamStreamingItem", "valueType": { - "$ref": "559" + "$ref": "575" }, "streamKind": "jsonl", "contentTypes": [ @@ -14799,7 +15189,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.receiveJsonLines" }, { - "$id": "923", + "$id": "947", "kind": "basic", "name": "receiveSse", "isExactName": false, @@ -14809,19 +15199,19 @@ "2024-08-16-preview" ], "operation": { - "$id": "924", + "$id": "948", "name": "receiveSse", "isExactName": false, "resourceName": "SampleTypeSpec", "accessibility": "public", "parameters": [ { - "$id": "925", + "$id": "949", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "202" + "$ref": "210" }, "isApiVersion": false, "optional": false, @@ -14832,12 +15222,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.receiveSse.accept", "methodParameterSegments": [ { - "$id": "926", + "$id": "950", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "202" + "$ref": "210" }, "location": "Header", "isApiVersion": false, @@ -14859,128 +15249,512 @@ 200 ], "bodyType": { - "$id": "927", + "$id": "951", "kind": "streaming", "name": "SSEStreamSampleEvents", "valueType": { - "$id": "928", + "$id": "952", "kind": "union", "name": "SampleEvents", "variantTypes": [ { - "$ref": "559" + "$ref": "575" }, { - "$ref": "204" + "$ref": "212" + } + ], + "namespace": "SampleTypeSpec", + "decorators": [], + "isExactName": false + }, + "streamKind": "sse", + "contentTypes": [ + "text/event-stream" + ], + "terminalEventValue": "[DONE]", + "crossLanguageDefinitionId": "TypeSpec.SSE.SSEStream" + }, + "headers": [ + { + "name": "contentType", + "nameInResponse": "content-type", + "type": { + "$ref": "214" + } + } + ], + "isErrorResponse": false, + "contentTypes": [ + "text/event-stream" + ], + "serializationOptions": {} + } + ], + "httpMethod": "GET", + "uri": "{sampleTypeSpecUrl}", + "path": "/streaming/sse/receive", + "bufferResponse": false, + "generateProtocolMethod": true, + "generateConvenienceMethod": true, + "crossLanguageDefinitionId": "SampleTypeSpec.receiveSse", + "decorators": [], + "namespace": "SampleTypeSpec" + }, + "parameters": [ + { + "$ref": "950" + } + ], + "response": { + "type": { + "$id": "953", + "kind": "streaming", + "name": "SSEStreamSampleEvents", + "valueType": { + "$ref": "952" + }, + "streamKind": "sse", + "contentTypes": [ + "text/event-stream" + ], + "terminalEventValue": "[DONE]", + "crossLanguageDefinitionId": "TypeSpec.SSE.SSEStream" + } + }, + "isOverride": false, + "generateConvenient": true, + "generateProtocol": true, + "crossLanguageDefinitionId": "SampleTypeSpec.receiveSse" + }, + { + "$id": "954", + "kind": "basic", + "name": "receiveExperimentalJsonLines", + "isExactName": false, + "accessibility": "public", + "apiVersions": [ + "2024-07-16-preview", + "2024-08-16-preview" + ], + "operation": { + "$id": "955", + "name": "receiveExperimentalJsonLines", + "isExactName": false, + "resourceName": "SampleTypeSpec", + "accessibility": "public", + "parameters": [ + { + "$id": "956", + "kind": "header", + "name": "accept", + "serializedName": "Accept", + "type": { + "$ref": "216" + }, + "isApiVersion": false, + "optional": false, + "isContentType": false, + "scope": "Constant", + "readOnly": false, + "decorators": [], + "crossLanguageDefinitionId": "SampleTypeSpec.receiveExperimentalJsonLines.accept", + "methodParameterSegments": [ + { + "$id": "957", + "kind": "method", + "name": "accept", + "serializedName": "Accept", + "type": { + "$ref": "216" + }, + "location": "Header", + "isApiVersion": false, + "optional": false, + "scope": "Constant", + "crossLanguageDefinitionId": "SampleTypeSpec.receiveExperimentalJsonLines.accept", + "readOnly": false, + "access": "public", + "decorators": [], + "isExactName": false + } + ], + "isExactName": false + } + ], + "responses": [ + { + "statusCodes": [ + 200 + ], + "bodyType": { + "$id": "958", + "kind": "streaming", + "name": "JsonlStreamPreviewDetails", + "valueType": { + "$ref": "578" + }, + "streamKind": "jsonl", + "contentTypes": [ + "application/jsonl" + ], + "crossLanguageDefinitionId": "TypeSpec.Http.Streams.JsonlStream" + }, + "headers": [ + { + "name": "contentType", + "nameInResponse": "content-type", + "type": { + "$ref": "218" + } + } + ], + "isErrorResponse": false, + "contentTypes": [ + "application/jsonl" + ], + "serializationOptions": { + "json": { + "name": "" + } + } + } + ], + "httpMethod": "GET", + "uri": "{sampleTypeSpecUrl}", + "path": "/experimental/jsonl", + "bufferResponse": false, + "generateProtocolMethod": true, + "generateConvenienceMethod": true, + "crossLanguageDefinitionId": "SampleTypeSpec.receiveExperimentalJsonLines", + "decorators": [], + "namespace": "SampleTypeSpec" + }, + "parameters": [ + { + "$ref": "957" + } + ], + "response": { + "type": { + "$id": "959", + "kind": "streaming", + "name": "JsonlStreamPreviewDetails", + "valueType": { + "$ref": "578" + }, + "streamKind": "jsonl", + "contentTypes": [ + "application/jsonl" + ], + "crossLanguageDefinitionId": "TypeSpec.Http.Streams.JsonlStream" + } + }, + "isOverride": false, + "generateConvenient": true, + "generateProtocol": true, + "crossLanguageDefinitionId": "SampleTypeSpec.receiveExperimentalJsonLines" + } + ], + "parameters": [ + { + "$id": "960", + "kind": "endpoint", + "name": "sampleTypeSpecUrl", + "serializedName": "sampleTypeSpecUrl", + "type": { + "$id": "961", + "kind": "url", + "name": "endpoint", + "crossLanguageDefinitionId": "TypeSpec.url" + }, + "isApiVersion": false, + "optional": false, + "scope": "Client", + "isEndpoint": true, + "serverUrlTemplate": "{sampleTypeSpecUrl}", + "skipUrlEncoding": false, + "readOnly": false, + "crossLanguageDefinitionId": "SampleTypeSpec.sampleTypeSpecUrl", + "isExactName": false + }, + { + "$ref": "858" + } + ], + "initializedBy": 1, + "decorators": [], + "crossLanguageDefinitionId": "SampleTypeSpec", + "apiVersions": [ + "2024-07-16-preview", + "2024-08-16-preview" + ], + "children": [ + { + "$id": "962", + "kind": "client", + "name": "ExperimentalSamples", + "isExactName": false, + "namespace": "SampleTypeSpec", + "methods": [ + { + "$id": "963", + "kind": "basic", + "name": "read", + "isExactName": false, + "accessibility": "public", + "apiVersions": [ + "2024-07-16-preview", + "2024-08-16-preview" + ], + "operation": { + "$id": "964", + "name": "read", + "isExactName": false, + "resourceName": "ExperimentalSamples", + "accessibility": "public", + "parameters": [ + { + "$id": "965", + "kind": "header", + "name": "accept", + "serializedName": "Accept", + "type": { + "$ref": "220" + }, + "isApiVersion": false, + "optional": false, + "isContentType": false, + "scope": "Constant", + "readOnly": false, + "decorators": [], + "crossLanguageDefinitionId": "SampleTypeSpec.ExperimentalSamples.read.accept", + "methodParameterSegments": [ + { + "$id": "966", + "kind": "method", + "name": "accept", + "serializedName": "Accept", + "type": { + "$ref": "220" + }, + "location": "Header", + "isApiVersion": false, + "optional": false, + "scope": "Constant", + "crossLanguageDefinitionId": "SampleTypeSpec.ExperimentalSamples.read.accept", + "readOnly": false, + "access": "public", + "decorators": [], + "isExactName": false + } + ], + "isExactName": false + } + ], + "responses": [ + { + "statusCodes": [ + 200 + ], + "bodyType": { + "$ref": "580" + }, + "headers": [], + "isErrorResponse": false, + "contentTypes": [ + "application/json" + ], + "serializationOptions": { + "json": { + "name": "" + } + } + } + ], + "httpMethod": "GET", + "uri": "{sampleTypeSpecUrl}", + "path": "/experimental", + "bufferResponse": true, + "generateProtocolMethod": true, + "generateConvenienceMethod": true, + "crossLanguageDefinitionId": "SampleTypeSpec.ExperimentalSamples.read", + "decorators": [], + "namespace": "SampleTypeSpec" + }, + "parameters": [ + { + "$ref": "966" + } + ], + "response": { + "type": { + "$ref": "580" + } + }, + "isOverride": false, + "generateConvenient": true, + "generateProtocol": true, + "crossLanguageDefinitionId": "SampleTypeSpec.ExperimentalSamples.read" + }, + { + "$id": "967", + "kind": "paging", + "name": "list", + "isExactName": false, + "accessibility": "public", + "apiVersions": [ + "2024-07-16-preview", + "2024-08-16-preview" + ], + "operation": { + "$id": "968", + "name": "list", + "isExactName": false, + "resourceName": "ExperimentalSamples", + "accessibility": "public", + "parameters": [ + { + "$id": "969", + "kind": "header", + "name": "accept", + "serializedName": "Accept", + "type": { + "$ref": "222" + }, + "isApiVersion": false, + "optional": false, + "isContentType": false, + "scope": "Constant", + "readOnly": false, + "decorators": [], + "crossLanguageDefinitionId": "SampleTypeSpec.ExperimentalSamples.list.accept", + "methodParameterSegments": [ + { + "$id": "970", + "kind": "method", + "name": "accept", + "serializedName": "Accept", + "type": { + "$ref": "222" + }, + "location": "Header", + "isApiVersion": false, + "optional": false, + "scope": "Constant", + "crossLanguageDefinitionId": "SampleTypeSpec.ExperimentalSamples.list.accept", + "readOnly": false, + "access": "public", + "decorators": [], + "isExactName": false } ], - "namespace": "SampleTypeSpec", - "decorators": [], "isExactName": false - }, - "streamKind": "sse", - "contentTypes": [ - "text/event-stream" - ], - "terminalEventValue": "[DONE]", - "crossLanguageDefinitionId": "TypeSpec.SSE.SSEStream" - }, - "headers": [ + } + ], + "responses": [ { - "name": "contentType", - "nameInResponse": "content-type", - "type": { - "$ref": "206" + "statusCodes": [ + 200 + ], + "bodyType": { + "$ref": "583" + }, + "headers": [], + "isErrorResponse": false, + "contentTypes": [ + "application/json" + ], + "serializationOptions": { + "json": { + "name": "" + } } } ], - "isErrorResponse": false, - "contentTypes": [ - "text/event-stream" + "httpMethod": "GET", + "uri": "{sampleTypeSpecUrl}", + "path": "/experimental/pages", + "bufferResponse": true, + "generateProtocolMethod": true, + "generateConvenienceMethod": true, + "crossLanguageDefinitionId": "SampleTypeSpec.ExperimentalSamples.list", + "decorators": [], + "namespace": "SampleTypeSpec" + }, + "parameters": [ + { + "$ref": "970" + } + ], + "response": { + "type": { + "$ref": "585" + }, + "resultSegments": [ + "items" + ] + }, + "isOverride": false, + "generateConvenient": true, + "generateProtocol": true, + "crossLanguageDefinitionId": "SampleTypeSpec.ExperimentalSamples.list", + "pagingMetadata": { + "itemPropertySegments": [ + "items" ], - "serializationOptions": {} + "pageSizeParameterSegments": [] } - ], - "httpMethod": "GET", - "uri": "{sampleTypeSpecUrl}", - "path": "/streaming/sse/receive", - "bufferResponse": false, - "generateProtocolMethod": true, - "generateConvenienceMethod": true, - "crossLanguageDefinitionId": "SampleTypeSpec.receiveSse", - "decorators": [], - "namespace": "SampleTypeSpec" - }, - "parameters": [ - { - "$ref": "926" } ], - "response": { - "type": { - "$id": "929", - "kind": "streaming", - "name": "SSEStreamSampleEvents", - "valueType": { - "$ref": "928" + "parameters": [ + { + "$id": "971", + "kind": "endpoint", + "name": "sampleTypeSpecUrl", + "serializedName": "sampleTypeSpecUrl", + "type": { + "$id": "972", + "kind": "url", + "name": "endpoint", + "crossLanguageDefinitionId": "TypeSpec.url" }, - "streamKind": "sse", - "contentTypes": [ - "text/event-stream" - ], - "terminalEventValue": "[DONE]", - "crossLanguageDefinitionId": "TypeSpec.SSE.SSEStream" + "isApiVersion": false, + "optional": false, + "scope": "Client", + "isEndpoint": true, + "serverUrlTemplate": "{sampleTypeSpecUrl}", + "skipUrlEncoding": false, + "readOnly": false, + "crossLanguageDefinitionId": "SampleTypeSpec.ExperimentalSamples.sampleTypeSpecUrl", + "isExactName": false } + ], + "initializedBy": 0, + "decorators": [], + "crossLanguageDefinitionId": "SampleTypeSpec.ExperimentalSamples", + "apiVersions": [ + "2024-07-16-preview", + "2024-08-16-preview" + ], + "parent": { + "$ref": "664" }, - "isOverride": false, - "generateConvenient": true, - "generateProtocol": true, - "crossLanguageDefinitionId": "SampleTypeSpec.receiveSse" - } - ], - "parameters": [ - { - "$id": "930", - "kind": "endpoint", - "name": "sampleTypeSpecUrl", - "serializedName": "sampleTypeSpecUrl", - "type": { - "$id": "931", - "kind": "url", - "name": "endpoint", - "crossLanguageDefinitionId": "TypeSpec.url" - }, - "isApiVersion": false, - "optional": false, - "scope": "Client", - "isEndpoint": true, - "serverUrlTemplate": "{sampleTypeSpecUrl}", - "skipUrlEncoding": false, - "readOnly": false, - "crossLanguageDefinitionId": "SampleTypeSpec.sampleTypeSpecUrl", - "isExactName": false + "isMultiServiceClient": false, + "experimental": { + "diagnosticId": "SAMPLE0009", + "dependsOn": [] + } }, { - "$ref": "834" - } - ], - "initializedBy": 1, - "decorators": [], - "crossLanguageDefinitionId": "SampleTypeSpec", - "apiVersions": [ - "2024-07-16-preview", - "2024-08-16-preview" - ], - "children": [ - { - "$id": "932", + "$id": "973", "kind": "client", "name": "AnimalOperations", "isExactName": false, "namespace": "SampleTypeSpec", "methods": [ { - "$id": "933", + "$id": "974", "kind": "basic", "name": "updatePetAsAnimal", "isExactName": false, @@ -14991,7 +15765,7 @@ ], "doc": "Update a pet as an animal", "operation": { - "$id": "934", + "$id": "975", "name": "updatePetAsAnimal", "isExactName": false, "resourceName": "AnimalOperations", @@ -14999,13 +15773,13 @@ "accessibility": "public", "parameters": [ { - "$id": "935", + "$id": "976", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "208" + "$ref": "224" }, "isApiVersion": false, "optional": false, @@ -15016,13 +15790,13 @@ "crossLanguageDefinitionId": "SampleTypeSpec.AnimalOperations.updatePetAsAnimal.contentType", "methodParameterSegments": [ { - "$id": "936", + "$id": "977", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "208" + "$ref": "224" }, "location": "Header", "isApiVersion": false, @@ -15038,12 +15812,12 @@ "isExactName": false }, { - "$id": "937", + "$id": "978", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "210" + "$ref": "226" }, "isApiVersion": false, "optional": false, @@ -15054,12 +15828,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.AnimalOperations.updatePetAsAnimal.accept", "methodParameterSegments": [ { - "$id": "938", + "$id": "979", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "210" + "$ref": "226" }, "location": "Header", "isApiVersion": false, @@ -15075,12 +15849,12 @@ "isExactName": false }, { - "$id": "939", + "$id": "980", "kind": "body", "name": "animal", "serializedName": "animal", "type": { - "$ref": "562" + "$ref": "586" }, "isApiVersion": false, "contentTypes": [ @@ -15094,12 +15868,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.AnimalOperations.updatePetAsAnimal.animal", "methodParameterSegments": [ { - "$id": "940", + "$id": "981", "kind": "method", "name": "animal", "serializedName": "animal", "type": { - "$ref": "562" + "$ref": "586" }, "location": "Body", "isApiVersion": false, @@ -15126,7 +15900,7 @@ 200 ], "bodyType": { - "$ref": "562" + "$ref": "586" }, "headers": [], "isErrorResponse": false, @@ -15155,18 +15929,18 @@ }, "parameters": [ { - "$ref": "940" + "$ref": "981" }, { - "$ref": "936" + "$ref": "977" }, { - "$ref": "938" + "$ref": "979" } ], "response": { "type": { - "$ref": "562" + "$ref": "586" } }, "isOverride": false, @@ -15175,7 +15949,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.AnimalOperations.updatePetAsAnimal" }, { - "$id": "941", + "$id": "982", "kind": "basic", "name": "updateDogAsAnimal", "isExactName": false, @@ -15186,7 +15960,7 @@ ], "doc": "Update a dog as an animal", "operation": { - "$id": "942", + "$id": "983", "name": "updateDogAsAnimal", "isExactName": false, "resourceName": "AnimalOperations", @@ -15194,13 +15968,13 @@ "accessibility": "public", "parameters": [ { - "$id": "943", + "$id": "984", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "212" + "$ref": "228" }, "isApiVersion": false, "optional": false, @@ -15211,13 +15985,13 @@ "crossLanguageDefinitionId": "SampleTypeSpec.AnimalOperations.updateDogAsAnimal.contentType", "methodParameterSegments": [ { - "$id": "944", + "$id": "985", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "212" + "$ref": "228" }, "location": "Header", "isApiVersion": false, @@ -15233,12 +16007,12 @@ "isExactName": false }, { - "$id": "945", + "$id": "986", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "214" + "$ref": "230" }, "isApiVersion": false, "optional": false, @@ -15249,12 +16023,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.AnimalOperations.updateDogAsAnimal.accept", "methodParameterSegments": [ { - "$id": "946", + "$id": "987", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "214" + "$ref": "230" }, "location": "Header", "isApiVersion": false, @@ -15270,12 +16044,12 @@ "isExactName": false }, { - "$id": "947", + "$id": "988", "kind": "body", "name": "animal", "serializedName": "animal", "type": { - "$ref": "562" + "$ref": "586" }, "isApiVersion": false, "contentTypes": [ @@ -15289,12 +16063,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.AnimalOperations.updateDogAsAnimal.animal", "methodParameterSegments": [ { - "$id": "948", + "$id": "989", "kind": "method", "name": "animal", "serializedName": "animal", "type": { - "$ref": "562" + "$ref": "586" }, "location": "Body", "isApiVersion": false, @@ -15321,7 +16095,7 @@ 200 ], "bodyType": { - "$ref": "562" + "$ref": "586" }, "headers": [], "isErrorResponse": false, @@ -15350,18 +16124,18 @@ }, "parameters": [ { - "$ref": "948" + "$ref": "989" }, { - "$ref": "944" + "$ref": "985" }, { - "$ref": "946" + "$ref": "987" } ], "response": { "type": { - "$ref": "562" + "$ref": "586" } }, "isOverride": false, @@ -15372,12 +16146,12 @@ ], "parameters": [ { - "$id": "949", + "$id": "990", "kind": "endpoint", "name": "sampleTypeSpecUrl", "serializedName": "sampleTypeSpecUrl", "type": { - "$id": "950", + "$id": "991", "kind": "url", "name": "endpoint", "crossLanguageDefinitionId": "TypeSpec.url" @@ -15401,19 +16175,19 @@ "2024-08-16-preview" ], "parent": { - "$ref": "640" + "$ref": "664" }, "isMultiServiceClient": false }, { - "$id": "951", + "$id": "992", "kind": "client", "name": "PetOperations", "isExactName": false, "namespace": "SampleTypeSpec", "methods": [ { - "$id": "952", + "$id": "993", "kind": "basic", "name": "updatePetAsPet", "isExactName": false, @@ -15424,7 +16198,7 @@ ], "doc": "Update a pet as a pet", "operation": { - "$id": "953", + "$id": "994", "name": "updatePetAsPet", "isExactName": false, "resourceName": "PetOperations", @@ -15432,13 +16206,13 @@ "accessibility": "public", "parameters": [ { - "$id": "954", + "$id": "995", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "216" + "$ref": "232" }, "isApiVersion": false, "optional": false, @@ -15449,13 +16223,13 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PetOperations.updatePetAsPet.contentType", "methodParameterSegments": [ { - "$id": "955", + "$id": "996", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "216" + "$ref": "232" }, "location": "Header", "isApiVersion": false, @@ -15471,12 +16245,12 @@ "isExactName": false }, { - "$id": "956", + "$id": "997", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "218" + "$ref": "234" }, "isApiVersion": false, "optional": false, @@ -15487,12 +16261,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PetOperations.updatePetAsPet.accept", "methodParameterSegments": [ { - "$id": "957", + "$id": "998", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "218" + "$ref": "234" }, "location": "Header", "isApiVersion": false, @@ -15508,12 +16282,12 @@ "isExactName": false }, { - "$id": "958", + "$id": "999", "kind": "body", "name": "pet", "serializedName": "pet", "type": { - "$ref": "567" + "$ref": "591" }, "isApiVersion": false, "contentTypes": [ @@ -15527,12 +16301,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PetOperations.updatePetAsPet.pet", "methodParameterSegments": [ { - "$id": "959", + "$id": "1000", "kind": "method", "name": "pet", "serializedName": "pet", "type": { - "$ref": "567" + "$ref": "591" }, "location": "Body", "isApiVersion": false, @@ -15559,7 +16333,7 @@ 200 ], "bodyType": { - "$ref": "567" + "$ref": "591" }, "headers": [], "isErrorResponse": false, @@ -15588,18 +16362,18 @@ }, "parameters": [ { - "$ref": "959" + "$ref": "1000" }, { - "$ref": "955" + "$ref": "996" }, { - "$ref": "957" + "$ref": "998" } ], "response": { "type": { - "$ref": "567" + "$ref": "591" } }, "isOverride": false, @@ -15608,7 +16382,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PetOperations.updatePetAsPet" }, { - "$id": "960", + "$id": "1001", "kind": "basic", "name": "updateDogAsPet", "isExactName": false, @@ -15619,7 +16393,7 @@ ], "doc": "Update a dog as a pet", "operation": { - "$id": "961", + "$id": "1002", "name": "updateDogAsPet", "isExactName": false, "resourceName": "PetOperations", @@ -15627,13 +16401,13 @@ "accessibility": "public", "parameters": [ { - "$id": "962", + "$id": "1003", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "220" + "$ref": "236" }, "isApiVersion": false, "optional": false, @@ -15644,13 +16418,13 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PetOperations.updateDogAsPet.contentType", "methodParameterSegments": [ { - "$id": "963", + "$id": "1004", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "220" + "$ref": "236" }, "location": "Header", "isApiVersion": false, @@ -15666,12 +16440,12 @@ "isExactName": false }, { - "$id": "964", + "$id": "1005", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "222" + "$ref": "238" }, "isApiVersion": false, "optional": false, @@ -15682,12 +16456,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PetOperations.updateDogAsPet.accept", "methodParameterSegments": [ { - "$id": "965", + "$id": "1006", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "222" + "$ref": "238" }, "location": "Header", "isApiVersion": false, @@ -15703,12 +16477,12 @@ "isExactName": false }, { - "$id": "966", + "$id": "1007", "kind": "body", "name": "pet", "serializedName": "pet", "type": { - "$ref": "567" + "$ref": "591" }, "isApiVersion": false, "contentTypes": [ @@ -15722,12 +16496,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PetOperations.updateDogAsPet.pet", "methodParameterSegments": [ { - "$id": "967", + "$id": "1008", "kind": "method", "name": "pet", "serializedName": "pet", "type": { - "$ref": "567" + "$ref": "591" }, "location": "Body", "isApiVersion": false, @@ -15754,7 +16528,7 @@ 200 ], "bodyType": { - "$ref": "567" + "$ref": "591" }, "headers": [], "isErrorResponse": false, @@ -15783,18 +16557,18 @@ }, "parameters": [ { - "$ref": "967" + "$ref": "1008" }, { - "$ref": "963" + "$ref": "1004" }, { - "$ref": "965" + "$ref": "1006" } ], "response": { "type": { - "$ref": "567" + "$ref": "591" } }, "isOverride": false, @@ -15805,12 +16579,12 @@ ], "parameters": [ { - "$id": "968", + "$id": "1009", "kind": "endpoint", "name": "sampleTypeSpecUrl", "serializedName": "sampleTypeSpecUrl", "type": { - "$id": "969", + "$id": "1010", "kind": "url", "name": "endpoint", "crossLanguageDefinitionId": "TypeSpec.url" @@ -15834,19 +16608,19 @@ "2024-08-16-preview" ], "parent": { - "$ref": "640" + "$ref": "664" }, "isMultiServiceClient": false }, { - "$id": "970", + "$id": "1011", "kind": "client", "name": "DogOperations", "isExactName": false, "namespace": "SampleTypeSpec", "methods": [ { - "$id": "971", + "$id": "1012", "kind": "basic", "name": "updateDogAsDog", "isExactName": false, @@ -15857,7 +16631,7 @@ ], "doc": "Update a dog as a dog", "operation": { - "$id": "972", + "$id": "1013", "name": "updateDogAsDog", "isExactName": false, "resourceName": "DogOperations", @@ -15865,13 +16639,13 @@ "accessibility": "public", "parameters": [ { - "$id": "973", + "$id": "1014", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "224" + "$ref": "240" }, "isApiVersion": false, "optional": false, @@ -15882,13 +16656,13 @@ "crossLanguageDefinitionId": "SampleTypeSpec.DogOperations.updateDogAsDog.contentType", "methodParameterSegments": [ { - "$id": "974", + "$id": "1015", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "doc": "Body parameter's content type. Known values are application/json", "type": { - "$ref": "224" + "$ref": "240" }, "location": "Header", "isApiVersion": false, @@ -15904,12 +16678,12 @@ "isExactName": false }, { - "$id": "975", + "$id": "1016", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "226" + "$ref": "242" }, "isApiVersion": false, "optional": false, @@ -15920,12 +16694,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.DogOperations.updateDogAsDog.accept", "methodParameterSegments": [ { - "$id": "976", + "$id": "1017", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "226" + "$ref": "242" }, "location": "Header", "isApiVersion": false, @@ -15941,12 +16715,12 @@ "isExactName": false }, { - "$id": "977", + "$id": "1018", "kind": "body", "name": "dog", "serializedName": "dog", "type": { - "$ref": "571" + "$ref": "595" }, "isApiVersion": false, "contentTypes": [ @@ -15960,12 +16734,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.DogOperations.updateDogAsDog.dog", "methodParameterSegments": [ { - "$id": "978", + "$id": "1019", "kind": "method", "name": "dog", "serializedName": "dog", "type": { - "$ref": "571" + "$ref": "595" }, "location": "Body", "isApiVersion": false, @@ -15992,7 +16766,7 @@ 200 ], "bodyType": { - "$ref": "571" + "$ref": "595" }, "headers": [], "isErrorResponse": false, @@ -16021,18 +16795,18 @@ }, "parameters": [ { - "$ref": "978" + "$ref": "1019" }, { - "$ref": "974" + "$ref": "1015" }, { - "$ref": "976" + "$ref": "1017" } ], "response": { "type": { - "$ref": "571" + "$ref": "595" } }, "isOverride": false, @@ -16043,12 +16817,12 @@ ], "parameters": [ { - "$id": "979", + "$id": "1020", "kind": "endpoint", "name": "sampleTypeSpecUrl", "serializedName": "sampleTypeSpecUrl", "type": { - "$id": "980", + "$id": "1021", "kind": "url", "name": "endpoint", "crossLanguageDefinitionId": "TypeSpec.url" @@ -16072,19 +16846,19 @@ "2024-08-16-preview" ], "parent": { - "$ref": "640" + "$ref": "664" }, "isMultiServiceClient": false }, { - "$id": "981", + "$id": "1022", "kind": "client", "name": "PlantOperations", "isExactName": false, "namespace": "SampleTypeSpec", "methods": [ { - "$id": "982", + "$id": "1023", "kind": "basic", "name": "getTree", "isExactName": false, @@ -16095,7 +16869,7 @@ ], "doc": "Get a tree as a plant", "operation": { - "$id": "983", + "$id": "1024", "name": "getTree", "isExactName": false, "resourceName": "PlantOperations", @@ -16103,12 +16877,12 @@ "accessibility": "public", "parameters": [ { - "$id": "984", + "$id": "1025", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "228" + "$ref": "244" }, "isApiVersion": false, "optional": false, @@ -16119,12 +16893,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PlantOperations.getTree.accept", "methodParameterSegments": [ { - "$id": "985", + "$id": "1026", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "228" + "$ref": "244" }, "location": "Header", "isApiVersion": false, @@ -16146,14 +16920,14 @@ 200 ], "bodyType": { - "$ref": "575" + "$ref": "599" }, "headers": [ { "name": "contentType", "nameInResponse": "content-type", "type": { - "$ref": "230" + "$ref": "246" } } ], @@ -16180,12 +16954,12 @@ }, "parameters": [ { - "$ref": "985" + "$ref": "1026" } ], "response": { "type": { - "$ref": "575" + "$ref": "599" } }, "isOverride": false, @@ -16194,7 +16968,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PlantOperations.getTree" }, { - "$id": "986", + "$id": "1027", "kind": "basic", "name": "getTreeAsJson", "isExactName": false, @@ -16205,7 +16979,7 @@ ], "doc": "Get a tree as a plant", "operation": { - "$id": "987", + "$id": "1028", "name": "getTreeAsJson", "isExactName": false, "resourceName": "PlantOperations", @@ -16213,12 +16987,12 @@ "accessibility": "public", "parameters": [ { - "$id": "988", + "$id": "1029", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "232" + "$ref": "248" }, "isApiVersion": false, "optional": false, @@ -16229,12 +17003,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PlantOperations.getTreeAsJson.accept", "methodParameterSegments": [ { - "$id": "989", + "$id": "1030", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "232" + "$ref": "248" }, "location": "Header", "isApiVersion": false, @@ -16256,14 +17030,14 @@ 200 ], "bodyType": { - "$ref": "575" + "$ref": "599" }, "headers": [ { "name": "contentType", "nameInResponse": "content-type", "type": { - "$ref": "234" + "$ref": "250" } } ], @@ -16290,12 +17064,12 @@ }, "parameters": [ { - "$ref": "989" + "$ref": "1030" } ], "response": { "type": { - "$ref": "575" + "$ref": "599" } }, "isOverride": false, @@ -16304,7 +17078,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PlantOperations.getTreeAsJson" }, { - "$id": "990", + "$id": "1031", "kind": "basic", "name": "updateTree", "isExactName": false, @@ -16315,7 +17089,7 @@ ], "doc": "Update a tree as a plant", "operation": { - "$id": "991", + "$id": "1032", "name": "updateTree", "isExactName": false, "resourceName": "PlantOperations", @@ -16323,12 +17097,12 @@ "accessibility": "public", "parameters": [ { - "$id": "992", + "$id": "1033", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "type": { - "$ref": "236" + "$ref": "252" }, "isApiVersion": false, "optional": false, @@ -16339,12 +17113,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PlantOperations.updateTree.contentType", "methodParameterSegments": [ { - "$id": "993", + "$id": "1034", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "type": { - "$ref": "236" + "$ref": "252" }, "location": "Header", "isApiVersion": false, @@ -16360,12 +17134,12 @@ "isExactName": false }, { - "$id": "994", + "$id": "1035", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "240" + "$ref": "256" }, "isApiVersion": false, "optional": false, @@ -16376,12 +17150,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PlantOperations.updateTree.accept", "methodParameterSegments": [ { - "$id": "995", + "$id": "1036", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "240" + "$ref": "256" }, "location": "Header", "isApiVersion": false, @@ -16397,12 +17171,12 @@ "isExactName": false }, { - "$id": "996", + "$id": "1037", "kind": "body", "name": "tree", "serializedName": "tree", "type": { - "$ref": "575" + "$ref": "599" }, "isApiVersion": false, "contentTypes": [ @@ -16416,12 +17190,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PlantOperations.updateTree.tree", "methodParameterSegments": [ { - "$id": "997", + "$id": "1038", "kind": "method", "name": "tree", "serializedName": "tree", "type": { - "$ref": "575" + "$ref": "599" }, "location": "Body", "isApiVersion": false, @@ -16448,14 +17222,14 @@ 200 ], "bodyType": { - "$ref": "575" + "$ref": "599" }, "headers": [ { "name": "contentType", "nameInResponse": "content-type", "type": { - "$ref": "242" + "$ref": "258" } } ], @@ -16485,18 +17259,18 @@ }, "parameters": [ { - "$ref": "997" + "$ref": "1038" }, { - "$ref": "993" + "$ref": "1034" }, { - "$ref": "995" + "$ref": "1036" } ], "response": { "type": { - "$ref": "575" + "$ref": "599" } }, "isOverride": false, @@ -16505,7 +17279,7 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PlantOperations.updateTree" }, { - "$id": "998", + "$id": "1039", "kind": "basic", "name": "updateTreeAsJson", "isExactName": false, @@ -16516,7 +17290,7 @@ ], "doc": "Update a tree as a plant", "operation": { - "$id": "999", + "$id": "1040", "name": "updateTreeAsJson", "isExactName": false, "resourceName": "PlantOperations", @@ -16524,12 +17298,12 @@ "accessibility": "public", "parameters": [ { - "$id": "1000", + "$id": "1041", "kind": "header", "name": "contentType", "serializedName": "Content-Type", "type": { - "$ref": "244" + "$ref": "260" }, "isApiVersion": false, "optional": false, @@ -16540,12 +17314,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PlantOperations.updateTreeAsJson.contentType", "methodParameterSegments": [ { - "$id": "1001", + "$id": "1042", "kind": "method", "name": "contentType", "serializedName": "Content-Type", "type": { - "$ref": "244" + "$ref": "260" }, "location": "Header", "isApiVersion": false, @@ -16561,12 +17335,12 @@ "isExactName": false }, { - "$id": "1002", + "$id": "1043", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "248" + "$ref": "264" }, "isApiVersion": false, "optional": false, @@ -16577,12 +17351,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PlantOperations.updateTreeAsJson.accept", "methodParameterSegments": [ { - "$id": "1003", + "$id": "1044", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "248" + "$ref": "264" }, "location": "Header", "isApiVersion": false, @@ -16598,12 +17372,12 @@ "isExactName": false }, { - "$id": "1004", + "$id": "1045", "kind": "body", "name": "tree", "serializedName": "tree", "type": { - "$ref": "575" + "$ref": "599" }, "isApiVersion": false, "contentTypes": [ @@ -16617,12 +17391,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.PlantOperations.updateTreeAsJson.tree", "methodParameterSegments": [ { - "$id": "1005", + "$id": "1046", "kind": "method", "name": "tree", "serializedName": "tree", "type": { - "$ref": "575" + "$ref": "599" }, "location": "Body", "isApiVersion": false, @@ -16649,14 +17423,14 @@ 200 ], "bodyType": { - "$ref": "575" + "$ref": "599" }, "headers": [ { "name": "contentType", "nameInResponse": "content-type", "type": { - "$ref": "250" + "$ref": "266" } } ], @@ -16686,18 +17460,18 @@ }, "parameters": [ { - "$ref": "1005" + "$ref": "1046" }, { - "$ref": "1001" + "$ref": "1042" }, { - "$ref": "1003" + "$ref": "1044" } ], "response": { "type": { - "$ref": "575" + "$ref": "599" } }, "isOverride": false, @@ -16708,12 +17482,12 @@ ], "parameters": [ { - "$id": "1006", + "$id": "1047", "kind": "endpoint", "name": "sampleTypeSpecUrl", "serializedName": "sampleTypeSpecUrl", "type": { - "$id": "1007", + "$id": "1048", "kind": "url", "name": "endpoint", "crossLanguageDefinitionId": "TypeSpec.url" @@ -16737,19 +17511,19 @@ "2024-08-16-preview" ], "parent": { - "$ref": "640" + "$ref": "664" }, "isMultiServiceClient": false }, { - "$id": "1008", + "$id": "1049", "kind": "client", "name": "Metrics", "isExactName": false, "namespace": "SampleTypeSpec", "methods": [ { - "$id": "1009", + "$id": "1050", "kind": "basic", "name": "getWidgetMetrics", "isExactName": false, @@ -16760,7 +17534,7 @@ ], "doc": "Get Widget metrics for given day of week", "operation": { - "$id": "1010", + "$id": "1051", "name": "getWidgetMetrics", "isExactName": false, "resourceName": "Metrics", @@ -16768,12 +17542,12 @@ "accessibility": "public", "parameters": [ { - "$id": "1011", + "$id": "1052", "kind": "path", "name": "metricsNamespace", "serializedName": "metricsNamespace", "type": { - "$id": "1012", + "$id": "1053", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -16791,12 +17565,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.Metrics.getWidgetMetrics.metricsNamespace", "methodParameterSegments": [ { - "$id": "1013", + "$id": "1054", "kind": "method", "name": "metricsNamespace", "serializedName": "metricsNamespace", "type": { - "$id": "1014", + "$id": "1055", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -16816,12 +17590,12 @@ "isExactName": false }, { - "$id": "1015", + "$id": "1056", "kind": "path", "name": "day", "serializedName": "day", "type": { - "$ref": "57" + "$ref": "65" }, "isApiVersion": false, "explode": false, @@ -16835,12 +17609,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.Metrics.getWidgetMetrics.day", "methodParameterSegments": [ { - "$id": "1016", + "$id": "1057", "kind": "method", "name": "day", "serializedName": "day", "type": { - "$ref": "57" + "$ref": "65" }, "location": "Path", "isApiVersion": false, @@ -16856,12 +17630,12 @@ "isExactName": false }, { - "$id": "1017", + "$id": "1058", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "252" + "$ref": "268" }, "isApiVersion": false, "optional": false, @@ -16872,12 +17646,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.Metrics.getWidgetMetrics.accept", "methodParameterSegments": [ { - "$id": "1018", + "$id": "1059", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "252" + "$ref": "268" }, "location": "Header", "isApiVersion": false, @@ -16899,7 +17673,7 @@ 200 ], "bodyType": { - "$ref": "586" + "$ref": "610" }, "headers": [], "isErrorResponse": false, @@ -16925,15 +17699,15 @@ }, "parameters": [ { - "$ref": "1016" + "$ref": "1057" }, { - "$ref": "1018" + "$ref": "1059" } ], "response": { "type": { - "$ref": "586" + "$ref": "610" } }, "isOverride": false, @@ -16944,12 +17718,12 @@ ], "parameters": [ { - "$id": "1019", + "$id": "1060", "kind": "endpoint", "name": "sampleTypeSpecUrl", "serializedName": "sampleTypeSpecUrl", "type": { - "$id": "1020", + "$id": "1061", "kind": "url", "name": "endpoint", "crossLanguageDefinitionId": "TypeSpec.url" @@ -16965,7 +17739,7 @@ "isExactName": false }, { - "$ref": "1013" + "$ref": "1054" } ], "initializedBy": 3, @@ -16976,19 +17750,19 @@ "2024-08-16-preview" ], "parent": { - "$ref": "640" + "$ref": "664" }, "isMultiServiceClient": false }, { - "$id": "1021", + "$id": "1062", "kind": "client", "name": "Notebooks", "isExactName": false, "namespace": "SampleTypeSpec", "methods": [ { - "$id": "1022", + "$id": "1063", "kind": "basic", "name": "getNotebook", "isExactName": false, @@ -16999,7 +17773,7 @@ ], "doc": "Get a notebook by name", "operation": { - "$id": "1023", + "$id": "1064", "name": "getNotebook", "isExactName": false, "resourceName": "Notebooks", @@ -17007,12 +17781,12 @@ "accessibility": "public", "parameters": [ { - "$id": "1024", + "$id": "1065", "kind": "path", "name": "notebookName", "serializedName": "notebookName", "type": { - "$id": "1025", + "$id": "1066", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -17030,12 +17804,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.Notebooks.getNotebook.notebookName", "methodParameterSegments": [ { - "$id": "1026", + "$id": "1067", "kind": "method", "name": "notebook", "serializedName": "notebook", "type": { - "$id": "1027", + "$id": "1068", "kind": "string", "name": "string", "crossLanguageDefinitionId": "TypeSpec.string", @@ -17056,12 +17830,12 @@ "isExactName": false }, { - "$id": "1028", + "$id": "1069", "kind": "header", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "254" + "$ref": "270" }, "isApiVersion": false, "optional": false, @@ -17072,12 +17846,12 @@ "crossLanguageDefinitionId": "SampleTypeSpec.Notebooks.getNotebook.accept", "methodParameterSegments": [ { - "$id": "1029", + "$id": "1070", "kind": "method", "name": "accept", "serializedName": "Accept", "type": { - "$ref": "254" + "$ref": "270" }, "location": "Header", "isApiVersion": false, @@ -17099,7 +17873,7 @@ 200 ], "bodyType": { - "$ref": "591" + "$ref": "615" }, "headers": [], "isErrorResponse": false, @@ -17125,12 +17899,12 @@ }, "parameters": [ { - "$ref": "1029" + "$ref": "1070" } ], "response": { "type": { - "$ref": "591" + "$ref": "615" } }, "isOverride": false, @@ -17141,12 +17915,12 @@ ], "parameters": [ { - "$id": "1030", + "$id": "1071", "kind": "endpoint", "name": "sampleTypeSpecUrl", "serializedName": "sampleTypeSpecUrl", "type": { - "$id": "1031", + "$id": "1072", "kind": "url", "name": "endpoint", "crossLanguageDefinitionId": "TypeSpec.url" @@ -17162,7 +17936,7 @@ "isExactName": false }, { - "$ref": "1026" + "$ref": "1067" } ], "initializedBy": 3, @@ -17173,7 +17947,7 @@ "2024-08-16-preview" ], "parent": { - "$ref": "640" + "$ref": "664" }, "isMultiServiceClient": false } diff --git a/packages/http-client-csharp/package-lock.json b/packages/http-client-csharp/package-lock.json index e83d9fe408a..a158d48c03d 100644 --- a/packages/http-client-csharp/package-lock.json +++ b/packages/http-client-csharp/package-lock.json @@ -20,6 +20,7 @@ "@typespec/compiler": "1.16.0", "@typespec/events": "0.86.0", "@typespec/http": "1.16.0", + "@typespec/http-client": "0.17.0", "@typespec/http-specs": "0.1.0-alpha.43", "@typespec/json-schema": "1.16.0", "@typespec/library-linter": "0.86.0", @@ -45,6 +46,7 @@ "@typespec/compiler": "^1.16.0", "@typespec/events": ">=0.86.0 <0.87.0 || ~0.87.0-0", "@typespec/http": "^1.16.0", + "@typespec/http-client": ">=0.17.0 <0.18.0 || ~0.18.0-0", "@typespec/openapi": "^1.16.0", "@typespec/rest": ">=0.86.0 <0.87.0 || ~0.87.0-0", "@typespec/sse": ">=0.86.0 <0.87.0 || ~0.87.0-0", @@ -66,6 +68,21 @@ "ws": "^8.21.0" } }, + "node_modules/@alloy-js/csharp": { + "version": "0.24.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@alloy-js/csharp/-/csharp-0.24.0.tgz", + "integrity": "sha1-3teiKMOBpttHQNseUhI2dmW4OGU=", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@alloy-js/core": "~0.24.0", + "@alloy-js/msbuild": "~0.24.0", + "change-case": "^5.4.4", + "marked": "^18.0.5", + "pathe": "^2.0.3" + } + }, "node_modules/@alloy-js/markdown": { "version": "0.24.0", "dev": true, @@ -75,6 +92,33 @@ "yaml": "^2.7.1" } }, + "node_modules/@alloy-js/msbuild": { + "version": "0.24.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@alloy-js/msbuild/-/msbuild-0.24.0.tgz", + "integrity": "sha1-CtpDJb2TbS+QcA+WHwkCzHTKCZQ=", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@alloy-js/core": "~0.24.0", + "change-case": "^5.4.4", + "marked": "^18.0.5", + "pathe": "^2.0.3" + } + }, + "node_modules/@alloy-js/python": { + "version": "0.5.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@alloy-js/python/-/python-0.5.0.tgz", + "integrity": "sha1-5jp01/A7C2FQRtAy6x9KXwv8QHQ=", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@alloy-js/core": "~0.24.0", + "change-case": "^5.4.4", + "pathe": "^2.0.3" + } + }, "node_modules/@alloy-js/typescript": { "version": "0.24.0", "dev": true, @@ -1533,6 +1577,21 @@ "node": ">=10" } }, + "node_modules/@typespec/emitter-framework": { + "version": "0.21.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@typespec/emitter-framework/-/emitter-framework-0.21.0.tgz", + "integrity": "sha512-ACVZ6cUpO+dmzA0xbBxYuYAWwkPp59kABxIES5BRvhKg873hyI7o3vM3Ni+m5FK4JWlBdw1oR4QINSNUt5rDCw==", + "dev": true, + "license": "MIT", + "peer": true, + "peerDependencies": { + "@alloy-js/core": "^0.24.1", + "@alloy-js/csharp": "^0.24.0", + "@alloy-js/python": "^0.5.0", + "@alloy-js/typescript": "^0.24.0", + "@typespec/compiler": "^1.16.0" + } + }, "node_modules/@typespec/events": { "version": "0.86.0", "resolved": "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-js/npm/registry/@typespec/events/-/events-0.86.0.tgz", @@ -1565,6 +1624,20 @@ } } }, + "node_modules/@typespec/http-client": { + "version": "0.17.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@typespec/http-client/-/http-client-0.17.0.tgz", + "integrity": "sha1-Z92YYnO4zIC0v8htDkxGrxjRuRk=", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@alloy-js/core": "^0.24.1", + "@alloy-js/typescript": "^0.24.0", + "@typespec/compiler": "^1.16.0", + "@typespec/emitter-framework": "^0.21.0", + "@typespec/http": "^1.16.0" + } + }, "node_modules/@typespec/http-specs": { "version": "0.1.0-alpha.43", "resolved": "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-js/npm/registry/@typespec/http-specs/-/http-specs-0.1.0-alpha.43.tgz", @@ -4009,6 +4082,20 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/marked": { + "version": "18.0.13", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/marked/-/marked-18.0.13.tgz", + "integrity": "sha512-xTxVzZsBFwunP6HDmtBkabUQEYArnP7/rMDGmPj9SlrKlQ4i8MdYVow+nJL0eOqwpUqhzBoTBRADGN6uYwPyOw==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/math-intrinsics/-/math-intrinsics-1.1.0.tgz", diff --git a/packages/http-client-csharp/package.json b/packages/http-client-csharp/package.json index 6cec4895c4a..4272f437120 100644 --- a/packages/http-client-csharp/package.json +++ b/packages/http-client-csharp/package.json @@ -63,6 +63,7 @@ "@typespec/compiler": "^1.16.0", "@typespec/events": ">=0.86.0 <0.87.0 || ~0.87.0-0", "@typespec/http": "^1.16.0", + "@typespec/http-client": ">=0.17.0 <0.18.0 || ~0.18.0-0", "@typespec/openapi": "^1.16.0", "@typespec/rest": ">=0.86.0 <0.87.0 || ~0.87.0-0", "@typespec/sse": ">=0.86.0 <0.87.0 || ~0.87.0-0", @@ -78,6 +79,7 @@ "@typespec/compiler": "1.16.0", "@typespec/events": "0.86.0", "@typespec/http": "1.16.0", + "@typespec/http-client": "0.17.0", "@typespec/http-specs": "0.1.0-alpha.43", "@typespec/json-schema": "1.16.0", "@typespec/library-linter": "0.86.0", diff --git a/packages/http-client-csharp/readme.md b/packages/http-client-csharp/readme.md index 39a4197c08e..48e54ace296 100644 --- a/packages/http-client-csharp/readme.md +++ b/packages/http-client-csharp/readme.md @@ -19,6 +19,83 @@ npm install @typespec/http-client-csharp For detailed instructions on how to customize the generated C# code, see the [Customization Guide](https://github.com/microsoft/typespec/blob/main/packages/http-client-csharp/.tspd/docs/customization.md). +### Experimental types and members + +Use `@TypeSpec.HttpClient.experimental` to assign a public diagnostic ID to a generated +type or member and identify experiments used by its implementation: + +```typespec +import "@typespec/http-client"; + +@TypeSpec.HttpClient.experimental(#{ + emitterScope: "@typespec/http-client-csharp", + diagnosticId: "C", + dependsOn: #["A", "B"], +}) +op bar(): void; +``` + +The C# emitter adds `[Experimental("C")]` to the corresponding generated declaration: + +| TypeSpec target | Generated C# target | +| ----------------------------------------------------- | ------------------------------------------------------------- | +| Model | Model class or struct | +| Model property | Property | +| Enum or union emitted as an enum | Enum or extensible-enum struct | +| Enum member or union variant emitted as an enum value | Enum field or extensible-enum property | +| Operation | Synchronous and asynchronous protocol and convenience methods | +| Namespace or interface emitted as a client | Client class | + +For example, models and their properties can be separate experiments: + +```typespec +@TypeSpec.HttpClient.experimental(#{ diagnosticId: "MODEL001" }) +model Preview { + @TypeSpec.HttpClient.experimental(#{ diagnosticId: "PROPERTY001" }) + value?: string; +} +``` + +Model factory methods expose the model's diagnostic. Partial serialization declarations +do not repeat the model attribute. Generated code suppresses diagnostics when referring +to source-annotated experimental types and members, so serialization, factories, and client +implementations can compile without changing the experimental status of other public APIs. + +For operation dependencies, suppressions surround each method declaration and body. +For type/member dependencies and generated references to experimental declarations, +suppressions are scoped to the generated file. Both include parameter and return types, +generic arguments, and implementation references; neither suppresses diagnostics in +consumer code. + +Dependencies identify diagnostics rather than individual types: one diagnostic can apply +to multiple types or members, including those defined in external libraries. For externally +mapped types, source `@experimental` metadata is retained for generated-reference suppressions; +the emitter does not generate the external declaration or add attributes to its library. +Other external experiments require explicit `dependsOn` entries. They are not discovered by reflection. + +Both metadata fields are optional. Without `diagnosticId`, no public experimental attribute +is added. Without `dependsOn`, no additional dependency diagnostics are requested; generated +references to source-annotated experiments are still handled. Emitter scopes apply to both fields. + +Diagnostic IDs must be single C# warning identifiers (ASCII letters, digits, and underscores, +not starting with a digit) or decimal warning numbers. Whitespace, punctuation, comments, and +line breaks are rejected with `invalid-experimental-diagnostic-id` before generating C#. +An `ExperimentalAttribute` on a customized partial client or method takes precedence over +the generated attribute. + +Some TypeSpec declarations have no corresponding C# declaration, such as scalars or unions +erased to built-in C# types without an explicit external mapping. C# also does not allow `ExperimentalAttribute` on parameters. +The emitter reports `experimental-target-not-supported` for these annotations instead of +silently dropping them or assigning their diagnostic to an unrelated API. + +Models referenced by a union retain their own experimental metadata. Annotate the model +declaration, not the union variant that references it: a model variant has no separate C# +declaration on which to place an attribute. + +Graduation is an explicit source change: dependencies becoming generally available, or +removing entries from `dependsOn`, does not remove `[Experimental("C")]`. Remove the +declaration's `@experimental` decorator when the public API is ready to graduate. + ## Emitter usage 1. Via the command line