From ca4f0d854e4e92aa64cc0f1fa0260785af712d53 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Thu, 10 Oct 2024 13:12:42 -0400 Subject: [PATCH 01/11] add Usage.ClientInitialization --- packages/typespec-client-generator-core/src/interfaces.ts | 2 ++ packages/typespec-client-generator-core/src/package.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/packages/typespec-client-generator-core/src/interfaces.ts b/packages/typespec-client-generator-core/src/interfaces.ts index cd789fb20..1d448f019 100644 --- a/packages/typespec-client-generator-core/src/interfaces.ts +++ b/packages/typespec-client-generator-core/src/interfaces.ts @@ -713,6 +713,8 @@ export enum UsageFlags { Json = 1 << 8, // Set when model is used in conjunction with an application/xml content type. Xml = 1 << 9, + // Set when model is used as client initialization model + ClientInitialization = 1 << 10, } interface SdkExampleBase { diff --git a/packages/typespec-client-generator-core/src/package.ts b/packages/typespec-client-generator-core/src/package.ts index 500fa0661..768716400 100644 --- a/packages/typespec-client-generator-core/src/package.ts +++ b/packages/typespec-client-generator-core/src/package.ts @@ -392,6 +392,7 @@ function getSdkInitializationType( clientParams.push(prop); } initializationModel.access = access; + initializationModel.usage = UsageFlags.ClientInitialization; } else { const namePrefix = client.kind === "SdkClient" ? client.name : client.groupPath; const name = `${namePrefix.split(".").at(-1)}Options`; From 24dca2d7550a1270de2f2deefea4c6363c300c1c Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Thu, 10 Oct 2024 13:12:56 -0400 Subject: [PATCH 02/11] add clientInititlization usage --- ...tcgc-addClientInitializationUsage-2024-9-10-13-12-49.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .chronus/changes/tcgc-addClientInitializationUsage-2024-9-10-13-12-49.md diff --git a/.chronus/changes/tcgc-addClientInitializationUsage-2024-9-10-13-12-49.md b/.chronus/changes/tcgc-addClientInitializationUsage-2024-9-10-13-12-49.md new file mode 100644 index 000000000..1630c0ad6 --- /dev/null +++ b/.chronus/changes/tcgc-addClientInitializationUsage-2024-9-10-13-12-49.md @@ -0,0 +1,7 @@ +--- +changeKind: feature +packages: + - "@azure-tools/typespec-client-generator-core" +--- + +git status \ No newline at end of file From b267cdf6f5d1ef16e18c8d65e9375831e57f2c4e Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Mon, 14 Oct 2024 14:14:05 -0400 Subject: [PATCH 03/11] fixing tests --- .../src/decorators.ts | 17 +---- .../src/package.ts | 68 +++++-------------- .../src/types.ts | 57 ++++++++++++++++ .../test/decorators.test.ts | 4 ++ 4 files changed, 80 insertions(+), 66 deletions(-) diff --git a/packages/typespec-client-generator-core/src/decorators.ts b/packages/typespec-client-generator-core/src/decorators.ts index d1e8be528..74dbb0b1d 100644 --- a/packages/typespec-client-generator-core/src/decorators.ts +++ b/packages/typespec-client-generator-core/src/decorators.ts @@ -1023,21 +1023,8 @@ export const $clientInitialization: ClientInitializationDecorator = ( export function getClientInitialization( context: TCGCContext, entity: Namespace | Interface, -): SdkInitializationType | undefined { - const model = getScopedDecoratorData(context, clientInitializationKey, entity); - if (!model) return model; - const sdkModel = getSdkModel(context, model); - const initializationProps = sdkModel.properties.map( - (property: SdkModelPropertyType): SdkMethodParameter => { - property.onClient = true; - property.kind = "method"; - return property as SdkMethodParameter; - }, - ); - return { - ...sdkModel, - properties: initializationProps, - }; +): Model | undefined { + return getScopedDecoratorData(context, clientInitializationKey, entity); } const paramAliasKey = createStateSymbol("paramAlias"); diff --git a/packages/typespec-client-generator-core/src/package.ts b/packages/typespec-client-generator-core/src/package.ts index 768716400..b4a4a4a22 100644 --- a/packages/typespec-client-generator-core/src/package.ts +++ b/packages/typespec-client-generator-core/src/package.ts @@ -3,7 +3,6 @@ import { createDiagnosticCollector, Diagnostic, getDoc, - getNamespaceFullName, getService, getSummary, ignoreDiagnostics, @@ -33,7 +32,6 @@ import { SdkEndpointType, SdkEnumType, SdkHttpOperation, - SdkInitializationType, SdkLroPagingServiceMethod, SdkLroServiceMetadata, SdkLroServiceMethod, @@ -53,7 +51,6 @@ import { SdkType, SdkUnionType, TCGCContext, - UsageFlags, } from "./interfaces.js"; import { createGeneratedName, @@ -80,9 +77,11 @@ import { } from "./public-utils.js"; import { addEncodeInfo, + createSdkInitializationTypeIfNonExist, getAllModelsWithDiagnostics, getClientTypeWithDiagnostics, getSdkCredentialParameter, + getSdkInitializationType, getSdkModelPropertyType, getTypeSpecBuiltInType, } from "./types.js"; @@ -375,45 +374,6 @@ function getClientDefaultApiVersion( return defaultVersion; } -function getSdkInitializationType( - context: TCGCContext, - client: SdkClient | SdkOperationGroup, -): [SdkInitializationType, readonly Diagnostic[]] { - const diagnostics = createDiagnosticCollector(); - let initializationModel = getClientInitialization(context, client.type); - let clientParams = context.__clientToParameters.get(client.type); - if (!clientParams) { - clientParams = []; - context.__clientToParameters.set(client.type, clientParams); - } - const access = client.kind === "SdkClient" ? "public" : "internal"; - if (initializationModel) { - for (const prop of initializationModel.properties) { - clientParams.push(prop); - } - initializationModel.access = access; - initializationModel.usage = UsageFlags.ClientInitialization; - } else { - const namePrefix = client.kind === "SdkClient" ? client.name : client.groupPath; - const name = `${namePrefix.split(".").at(-1)}Options`; - initializationModel = { - __raw: client.service, - doc: "Initialization class for the client", - kind: "model", - properties: [], - name, - isGeneratedName: true, - access, - usage: UsageFlags.Input, - crossLanguageDefinitionId: `${getNamespaceFullName(client.service.namespace!)}.${name}`, - apiVersions: context.__tspTypeToApiVersions.get(client.type)!, - decorators: [], - }; - } - - return diagnostics.wrap(initializationModel); -} - function getSdkMethodParameter( context: TCGCContext, type: Type, @@ -464,9 +424,10 @@ function getSdkMethods( const operationGroupClient = diagnostics.pipe( createSdkClientType(context, operationGroup, sdkClientType), ); - const clientInitialization = getClientInitialization(context, operationGroup.type); + const tspClientInitialization = getClientInitialization(context, operationGroup.type); const parameters: SdkParameter[] = []; - if (clientInitialization) { + if (tspClientInitialization) { + const clientInitialization = getSdkInitializationType(context, operationGroup, tspClientInitialization); for (const property of clientInitialization.properties) { parameters.push(property); } @@ -634,6 +595,10 @@ function createSdkClientType( } else { name = getClientNameOverride(context, client.type) ?? client.type.name; } + const tspInitializationModel = getClientInitialization(context, client.type); + const initialization = tspInitializationModel + ? getSdkInitializationType(context, client, tspInitializationModel) + : createSdkInitializationTypeIfNonExist(context, client); const sdkClientType: SdkClientType = { __raw: client, kind: "client", @@ -643,7 +608,7 @@ function createSdkClientType( methods: [], apiVersions: context.__tspTypeToApiVersions.get(client.type)!, nameSpace: getClientNamespaceStringHelper(context, client.service)!, - initialization: diagnostics.pipe(getSdkInitializationType(context, client)), + initialization, decorators: diagnostics.pipe(getTypeDecorators(context, client.type)), parent, // if it is client, the crossLanguageDefinitionId is the ${namespace}, if it is operation group, the crosslanguageDefinitionId is the %{namespace}.%{operationGroupName} @@ -662,15 +627,19 @@ function addDefaultClientParameters< >(context: TCGCContext, client: SdkClientType): void { const diagnostics = createDiagnosticCollector(); // there will always be an endpoint property - client.initialization.properties.push(diagnostics.pipe(getSdkEndpointParameter(context, client))); + if (!client.initialization.properties.find((x) => x.kind === "endpoint")) { + client.initialization.properties.push(diagnostics.pipe(getSdkEndpointParameter(context, client))); + } const credentialParam = getSdkCredentialParameter(context, client.__raw); - if (credentialParam) { + if (credentialParam && !client.initialization.properties.find((x) => x.kind === "credential")) { client.initialization.properties.push(credentialParam); } let apiVersionParam = context.__clientToParameters .get(client.__raw.type) ?.find((x) => x.isApiVersionParam); - if (!apiVersionParam) { + if (apiVersionParam) { + client.initialization.properties.push(apiVersionParam); + } else { for (const operationGroup of listOperationGroups(context, client.__raw)) { // if any sub operation groups have an api version param, the top level needs // the api version param as well @@ -680,9 +649,6 @@ function addDefaultClientParameters< if (apiVersionParam) break; } } - if (apiVersionParam) { - client.initialization.properties.push(apiVersionParam); - } let subId = context.__clientToParameters .get(client.__raw.type) ?.find((x) => isSubscriptionId(context, x)); diff --git a/packages/typespec-client-generator-core/src/types.ts b/packages/typespec-client-generator-core/src/types.ts index c39d338b7..f9696d0e2 100644 --- a/packages/typespec-client-generator-core/src/types.ts +++ b/packages/typespec-client-generator-core/src/types.ts @@ -24,6 +24,7 @@ import { getDoc, getEncode, getKnownValues, + getNamespaceFullName, getSummary, getVisibility, ignoreDiagnostics, @@ -43,6 +44,7 @@ import { } from "@typespec/http"; import { getAccessOverride, + getClientInitialization, getOverriddenClientMethod, getUsageOverride, listClients, @@ -67,6 +69,7 @@ import { SdkEnumType, SdkEnumValueType, SdkInitializationType, + SdkMethodParameter, SdkModelPropertyType, SdkModelPropertyTypeBase, SdkModelType, @@ -781,6 +784,60 @@ function getSdkEnumValueType( return diagnostics.wrap(getTypeSpecBuiltInType(context, kind!)); } +export function createSdkInitializationTypeIfNonExist(context: TCGCContext, client: SdkClient | SdkOperationGroup): SdkInitializationType { + const namePrefix = client.kind === "SdkClient" ? client.name : client.groupPath; + const name = `${namePrefix.split(".").at(-1)}Options`; + return { + __raw: client.service, + doc: "Initialization class for the client", + kind: "model", + properties: [], + name, + isGeneratedName: true, + access: client.kind === "SdkClient" ? "public" : "internal", + usage: UsageFlags.Input, + crossLanguageDefinitionId: `${getNamespaceFullName(client.service.namespace!)}.${name}`, + apiVersions: context.__tspTypeToApiVersions.get(client.type)!, + decorators: [], + }; +} + +export function getSdkInitializationType( + context: TCGCContext, + client: SdkClient | SdkOperationGroup, + model: Model, +): SdkInitializationType { + // convert to SDK type + const sdkModel = getSdkModel(context, model); + const initializationProps = sdkModel.properties.map( + (property: SdkModelPropertyType): SdkMethodParameter => { + property.onClient = true; + property.kind = "method"; + return property as SdkMethodParameter; + }, + ); + const initializationModel = { + ...sdkModel, + properties: initializationProps, + }; + + + let clientParams = context.__clientToParameters.get(client.type); + if (!clientParams) { + clientParams = []; + context.__clientToParameters.set(client.type, clientParams); + } + + for (const prop of initializationModel.properties) { + clientParams.push(prop); + } + updateUsageOrAccessOfModel(context, UsageFlags.ClientInitialization, initializationModel) + updateUsageOrAccessOfModel(context, client.kind === "SdkClient" ? "public" : "internal", initializationModel) + initializationModel.usage = UsageFlags.ClientInitialization; + updateModelsMap(context, model, initializationModel); + return initializationModel; +} + function getUnionAsEnumValueType( context: TCGCContext, union: Union, diff --git a/packages/typespec-client-generator-core/test/decorators.test.ts b/packages/typespec-client-generator-core/test/decorators.test.ts index 666145f0b..f368d0f9b 100644 --- a/packages/typespec-client-generator-core/test/decorators.test.ts +++ b/packages/typespec-client-generator-core/test/decorators.test.ts @@ -2534,6 +2534,10 @@ describe("typespec-client-generator-core: decorators", () => { strictEqual(blobNameOpParam.correspondingMethodParams.length, 1); strictEqual(blobNameOpParam.correspondingMethodParams[0], blobName); strictEqual(blobNameOpParam.onClient, true); + + strictEqual(sdkPackage.models.length, 1); + const clientInitializationModel = sdkPackage.models[0]; + ok(clientInitializationModel.usage & UsageFlags.ClientInitialization); }); it("On Interface", async () => { From 6836ecb0a02ee41ba8293693224dafc08ae18d0a Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Tue, 15 Oct 2024 11:12:44 -0400 Subject: [PATCH 04/11] all passing except for new test --- .../src/package.ts | 23 ++++++++++--------- .../src/types.ts | 7 +++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/typespec-client-generator-core/src/package.ts b/packages/typespec-client-generator-core/src/package.ts index b4a4a4a22..1b3fd379c 100644 --- a/packages/typespec-client-generator-core/src/package.ts +++ b/packages/typespec-client-generator-core/src/package.ts @@ -637,18 +637,19 @@ function addDefaultClientParameters< let apiVersionParam = context.__clientToParameters .get(client.__raw.type) ?.find((x) => x.isApiVersionParam); - if (apiVersionParam) { - client.initialization.properties.push(apiVersionParam); - } else { - for (const operationGroup of listOperationGroups(context, client.__raw)) { - // if any sub operation groups have an api version param, the top level needs - // the api version param as well - apiVersionParam = context.__clientToParameters - .get(operationGroup.type) - ?.find((x) => x.isApiVersionParam); - if (apiVersionParam) break; + if (!apiVersionParam) { + for (const operationGroup of listOperationGroups(context, client.__raw)) { + // if any sub operation groups have an api version param, the top level needs + // the api version param as well + apiVersionParam = context.__clientToParameters + .get(operationGroup.type) + ?.find((x) => x.isApiVersionParam); + if (apiVersionParam) break; + } + } + if (apiVersionParam) { + client.initialization.properties.push(apiVersionParam); } - } let subId = context.__clientToParameters .get(client.__raw.type) ?.find((x) => isSubscriptionId(context, x)); diff --git a/packages/typespec-client-generator-core/src/types.ts b/packages/typespec-client-generator-core/src/types.ts index f9696d0e2..8af70ed6c 100644 --- a/packages/typespec-client-generator-core/src/types.ts +++ b/packages/typespec-client-generator-core/src/types.ts @@ -816,8 +816,10 @@ export function getSdkInitializationType( return property as SdkMethodParameter; }, ); - const initializationModel = { + const initializationModel: SdkInitializationType = { ...sdkModel, + usage: UsageFlags.ClientInitialization, + access: client.kind === "SdkClient" ? "public" : "internal", properties: initializationProps, }; @@ -831,9 +833,6 @@ export function getSdkInitializationType( for (const prop of initializationModel.properties) { clientParams.push(prop); } - updateUsageOrAccessOfModel(context, UsageFlags.ClientInitialization, initializationModel) - updateUsageOrAccessOfModel(context, client.kind === "SdkClient" ? "public" : "internal", initializationModel) - initializationModel.usage = UsageFlags.ClientInitialization; updateModelsMap(context, model, initializationModel); return initializationModel; } From b9bf5363694cc434c6043344f783d4fc16d0f9d8 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Wed, 16 Oct 2024 17:26:48 -0400 Subject: [PATCH 05/11] only one test failing --- .../src/interfaces.ts | 12 +- .../src/package.ts | 19 ++-- .../src/types.ts | 85 +++++++------- .../test/decorators.test.ts | 88 +++++++-------- .../test/package.test.ts | 18 +-- .../test/packages/client.test.ts | 104 +++++++++--------- 6 files changed, 169 insertions(+), 157 deletions(-) diff --git a/packages/typespec-client-generator-core/src/interfaces.ts b/packages/typespec-client-generator-core/src/interfaces.ts index 1d448f019..6cb6a600a 100644 --- a/packages/typespec-client-generator-core/src/interfaces.ts +++ b/packages/typespec-client-generator-core/src/interfaces.ts @@ -350,9 +350,10 @@ export interface SdkUnionType extends export type AccessFlags = "internal" | "public"; -export interface SdkModelType extends SdkTypeBase { +export interface SdkModelType + extends SdkTypeBase { kind: "model"; - properties: SdkModelPropertyType[]; + properties: TPropertyType[]; name: string; isGeneratedName: boolean; access: AccessFlags; @@ -360,14 +361,15 @@ export interface SdkModelType extends SdkTypeBase { additionalProperties?: SdkType; discriminatorValue?: string; discriminatedSubtypes?: Record; - discriminatorProperty?: SdkModelPropertyType; + discriminatorProperty?: TPropertyType; baseModel?: SdkModelType; crossLanguageDefinitionId: string; apiVersions: string[]; } -export interface SdkInitializationType extends SdkModelType { - properties: SdkParameter[]; +export interface SdkInitializationType { + access: AccessFlags; + model: SdkModelType; } export interface SdkCredentialType extends SdkTypeBase { diff --git a/packages/typespec-client-generator-core/src/package.ts b/packages/typespec-client-generator-core/src/package.ts index 1b3fd379c..b958c1440 100644 --- a/packages/typespec-client-generator-core/src/package.ts +++ b/packages/typespec-client-generator-core/src/package.ts @@ -428,8 +428,11 @@ function getSdkMethods( const parameters: SdkParameter[] = []; if (tspClientInitialization) { const clientInitialization = getSdkInitializationType(context, operationGroup, tspClientInitialization); - for (const property of clientInitialization.properties) { - parameters.push(property); + for (const property of clientInitialization.model.properties) { + if (property.kind === "method") { + parameters.push(property); + } + } } else { } @@ -627,12 +630,12 @@ function addDefaultClientParameters< >(context: TCGCContext, client: SdkClientType): void { const diagnostics = createDiagnosticCollector(); // there will always be an endpoint property - if (!client.initialization.properties.find((x) => x.kind === "endpoint")) { - client.initialization.properties.push(diagnostics.pipe(getSdkEndpointParameter(context, client))); + if (!client.initialization.model.properties.find((x) => x.kind === "endpoint")) { + client.initialization.model.properties.push(diagnostics.pipe(getSdkEndpointParameter(context, client))); } const credentialParam = getSdkCredentialParameter(context, client.__raw); - if (credentialParam && !client.initialization.properties.find((x) => x.kind === "credential")) { - client.initialization.properties.push(credentialParam); + if (credentialParam && !client.initialization.model.properties.find((x) => x.kind === "credential")) { + client.initialization.model.properties.push(credentialParam); } let apiVersionParam = context.__clientToParameters .get(client.__raw.type) @@ -648,7 +651,7 @@ function addDefaultClientParameters< } } if (apiVersionParam) { - client.initialization.properties.push(apiVersionParam); + client.initialization.model.properties.push(apiVersionParam); } let subId = context.__clientToParameters .get(client.__raw.type) @@ -663,7 +666,7 @@ function addDefaultClientParameters< } } if (subId) { - client.initialization.properties.push(subId); + client.initialization.model.properties.push(subId); } } diff --git a/packages/typespec-client-generator-core/src/types.ts b/packages/typespec-client-generator-core/src/types.ts index 8af70ed6c..7668bcac8 100644 --- a/packages/typespec-client-generator-core/src/types.ts +++ b/packages/typespec-client-generator-core/src/types.ts @@ -74,6 +74,7 @@ import { SdkModelPropertyTypeBase, SdkModelType, SdkOperationGroup, + SdkParameter, SdkTupleType, SdkType, SdkUnionType, @@ -688,18 +689,6 @@ export function getSdkModel( return ignoreDiagnostics(getSdkModelWithDiagnostics(context, type, operation)); } -export function getInitializationType( - context: TCGCContext, - type: Model, - operation?: Operation, -): SdkInitializationType { - const model = ignoreDiagnostics(getSdkModelWithDiagnostics(context, type, operation)); - for (const property of model.properties) { - property.kind = "method"; - } - return model as SdkInitializationType; -} - export function getSdkModelWithDiagnostics( context: TCGCContext, type: Model, @@ -784,21 +773,27 @@ function getSdkEnumValueType( return diagnostics.wrap(getTypeSpecBuiltInType(context, kind!)); } -export function createSdkInitializationTypeIfNonExist(context: TCGCContext, client: SdkClient | SdkOperationGroup): SdkInitializationType { +export function createSdkInitializationTypeIfNonExist( + context: TCGCContext, + client: SdkClient | SdkOperationGroup, +): SdkInitializationType { const namePrefix = client.kind === "SdkClient" ? client.name : client.groupPath; const name = `${namePrefix.split(".").at(-1)}Options`; return { - __raw: client.service, - doc: "Initialization class for the client", - kind: "model", - properties: [], - name, - isGeneratedName: true, access: client.kind === "SdkClient" ? "public" : "internal", - usage: UsageFlags.Input, - crossLanguageDefinitionId: `${getNamespaceFullName(client.service.namespace!)}.${name}`, - apiVersions: context.__tspTypeToApiVersions.get(client.type)!, - decorators: [], + model: { + __raw: client.service, + doc: "Initialization class for the client", + kind: "model", + properties: [], + name, + isGeneratedName: true, + access: "public", + usage: UsageFlags.Input | UsageFlags.ClientInitialization, + crossLanguageDefinitionId: `${getNamespaceFullName(client.service.namespace!)}.${name}`, + apiVersions: context.__tspTypeToApiVersions.get(client.type)!, + decorators: [], + }, }; } @@ -808,32 +803,40 @@ export function getSdkInitializationType( model: Model, ): SdkInitializationType { // convert to SDK type - const sdkModel = getSdkModel(context, model); - const initializationProps = sdkModel.properties.map( - (property: SdkModelPropertyType): SdkMethodParameter => { - property.onClient = true; - property.kind = "method"; - return property as SdkMethodParameter; - }, - ); + const existingModel = context.modelsMap?.get(model) as SdkModelType | undefined; + let sdkModel: SdkModelType; + if (existingModel) { + sdkModel = existingModel; + } else { + sdkModel = getSdkModel(context, model) as SdkModelType; + + sdkModel.properties = sdkModel.properties.map( + (property: SdkModelPropertyType): SdkMethodParameter => { + property.onClient = true; + property.kind = "method"; + return property as SdkMethodParameter; + }, + ); + } const initializationModel: SdkInitializationType = { - ...sdkModel, - usage: UsageFlags.ClientInitialization, access: client.kind === "SdkClient" ? "public" : "internal", - properties: initializationProps, + model: sdkModel, }; - - let clientParams = context.__clientToParameters.get(client.type); if (!clientParams) { clientParams = []; context.__clientToParameters.set(client.type, clientParams); } - - for (const prop of initializationModel.properties) { + + for (const prop of initializationModel.model.properties) { + if (!clientParams.filter((p) => p.name === prop.name).length) clientParams.push(prop); } - updateModelsMap(context, model, initializationModel); + updateUsageOrAccessOfModel(context, UsageFlags.Input, sdkModel, { propagation: false }); + updateUsageOrAccessOfModel(context, UsageFlags.ClientInitialization, sdkModel, { + propagation: false, + }); + updateModelsMap(context, model, sdkModel); return initializationModel; } @@ -1834,6 +1837,10 @@ export function getAllModelsWithDiagnostics( diagnostics.pipe(updateTypesFromOperation(context, operation)); } const ogs = listOperationGroups(context, client); + const clientInitModel = getClientInitialization(context, client.type); + if (clientInitModel) { + getSdkInitializationType(context, client, clientInitModel); + } while (ogs.length) { const operationGroup = ogs.pop(); for (const operation of listOperationsInOperationGroup(context, operationGroup!)) { diff --git a/packages/typespec-client-generator-core/test/decorators.test.ts b/packages/typespec-client-generator-core/test/decorators.test.ts index f368d0f9b..0285b9398 100644 --- a/packages/typespec-client-generator-core/test/decorators.test.ts +++ b/packages/typespec-client-generator-core/test/decorators.test.ts @@ -1158,7 +1158,7 @@ describe("typespec-client-generator-core: decorators", () => { const sdkPackage = runnerWithVersion.context.sdkPackage; strictEqual(sdkPackage.clients.length, 1); - const apiVersionParam = sdkPackage.clients[0].initialization.properties.find( + const apiVersionParam = sdkPackage.clients[0].initialization.model.properties.find( (x) => x.isApiVersionParam, ); ok(apiVersionParam); @@ -1257,7 +1257,7 @@ describe("typespec-client-generator-core: decorators", () => { const sdkPackage = runnerWithVersion.context.sdkPackage; strictEqual(sdkPackage.clients.length, 1); - const apiVersionParam = sdkPackage.clients[0].initialization.properties.find( + const apiVersionParam = sdkPackage.clients[0].initialization.model.properties.find( (x) => x.isApiVersionParam, ); ok(apiVersionParam); @@ -1355,7 +1355,7 @@ describe("typespec-client-generator-core: decorators", () => { const sdkPackage = runnerWithVersion.context.sdkPackage; strictEqual(sdkPackage.clients.length, 1); - const apiVersionParam = sdkPackage.clients[0].initialization.properties.find( + const apiVersionParam = sdkPackage.clients[0].initialization.model.properties.find( (x) => x.isApiVersionParam, ); ok(apiVersionParam); @@ -1453,7 +1453,7 @@ describe("typespec-client-generator-core: decorators", () => { const sdkPackage = runnerWithVersion.context.sdkPackage; strictEqual(sdkPackage.clients.length, 1); - const apiVersionParam = sdkPackage.clients[0].initialization.properties.find( + const apiVersionParam = sdkPackage.clients[0].initialization.model.properties.find( (x) => x.isApiVersionParam, ); ok(apiVersionParam); @@ -1554,7 +1554,7 @@ describe("typespec-client-generator-core: decorators", () => { const sdkPackage = runnerWithVersion.context.sdkPackage; strictEqual(sdkPackage.clients.length, 1); - const apiVersionParam = sdkPackage.clients[0].initialization.properties.find( + const apiVersionParam = sdkPackage.clients[0].initialization.model.properties.find( (x) => x.isApiVersionParam, ); ok(apiVersionParam); @@ -1643,7 +1643,7 @@ describe("typespec-client-generator-core: decorators", () => { const sdkPackage = runnerWithVersion.context.sdkPackage; strictEqual(sdkPackage.clients.length, 1); - const apiVersionParam = sdkPackage.clients[0].initialization.properties.find( + const apiVersionParam = sdkPackage.clients[0].initialization.model.properties.find( (x) => x.isApiVersionParam, ); ok(apiVersionParam); @@ -1795,8 +1795,8 @@ describe("typespec-client-generator-core: decorators", () => { ok(versioningClient); strictEqual(versioningClient.methods.length, 2); - strictEqual(versioningClient.initialization.properties.length, 1); - const versioningClientEndpoint = versioningClient.initialization.properties.find( + strictEqual(versioningClient.initialization.model.properties.length, 1); + const versioningClientEndpoint = versioningClient.initialization.model.properties.find( (x) => x.kind === "endpoint", ); ok(versioningClientEndpoint); @@ -1817,8 +1817,8 @@ describe("typespec-client-generator-core: decorators", () => { ok(interfaceV2); strictEqual(interfaceV2.methods.length, 1); - strictEqual(interfaceV2.initialization.properties.length, 1); - const interfaceV2Endpoint = interfaceV2.initialization.properties.find( + strictEqual(interfaceV2.initialization.model.properties.length, 1); + const interfaceV2Endpoint = interfaceV2.initialization.model.properties.find( (x) => x.kind === "endpoint", ); ok(interfaceV2Endpoint); @@ -2511,10 +2511,10 @@ describe("typespec-client-generator-core: decorators", () => { ); const sdkPackage = runner.context.sdkPackage; const client = sdkPackage.clients[0]; - strictEqual(client.initialization.properties.length, 2); - const endpoint = client.initialization.properties.find((x) => x.kind === "endpoint"); + strictEqual(client.initialization.model.properties.length, 2); + const endpoint = client.initialization.model.properties.find((x) => x.kind === "endpoint"); ok(endpoint); - const blobName = client.initialization.properties.find((x) => x.name === "blobName"); + const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); ok(blobName); strictEqual(blobName.clientDefaultValue, undefined); strictEqual(blobName.onClient, true); @@ -2615,9 +2615,9 @@ describe("typespec-client-generator-core: decorators", () => { const client = clients[0]; strictEqual(client.name, "StorageClient"); strictEqual(client.initialization.access, "public"); - strictEqual(client.initialization.properties.length, 2); - ok(client.initialization.properties.find((x) => x.kind === "endpoint")); - const blobName = client.initialization.properties.find((x) => x.name === "blobName"); + strictEqual(client.initialization.model.properties.length, 2); + ok(client.initialization.model.properties.find((x) => x.kind === "endpoint")); + const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); ok(blobName); strictEqual(blobName.onClient, true); @@ -2645,10 +2645,10 @@ describe("typespec-client-generator-core: decorators", () => { strictEqual(blobClient.kind, "client"); strictEqual(blobClient.name, "BlobClient"); strictEqual(blobClient.initialization.access, "internal"); - strictEqual(blobClient.initialization.properties.length, 2); + strictEqual(blobClient.initialization.model.properties.length, 2); - ok(blobClient.initialization.properties.find((x) => x.kind === "endpoint")); - const blobClientBlobInitializationProp = blobClient.initialization.properties.find( + ok(blobClient.initialization.model.properties.find((x) => x.kind === "endpoint")); + const blobClientBlobInitializationProp = blobClient.initialization.model.properties.find( (x) => x.name === "blobName", ); ok(blobClientBlobInitializationProp); @@ -2690,10 +2690,10 @@ describe("typespec-client-generator-core: decorators", () => { ); const sdkPackage = runner.context.sdkPackage; const client = sdkPackage.clients[0]; - strictEqual(client.initialization.properties.length, 2); - const endpoint = client.initialization.properties.find((x) => x.kind === "endpoint"); + strictEqual(client.initialization.model.properties.length, 2); + const endpoint = client.initialization.model.properties.find((x) => x.kind === "endpoint"); ok(endpoint); - const blobName = client.initialization.properties.find((x) => x.name === "blobName"); + const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); ok(blobName); strictEqual(blobName.clientDefaultValue, undefined); strictEqual(blobName.onClient, true); @@ -2747,16 +2747,16 @@ describe("typespec-client-generator-core: decorators", () => { ); const sdkPackage = runner.context.sdkPackage; const client = sdkPackage.clients[0]; - strictEqual(client.initialization.properties.length, 3); - const endpoint = client.initialization.properties.find((x) => x.kind === "endpoint"); + strictEqual(client.initialization.model.properties.length, 3); + const endpoint = client.initialization.model.properties.find((x) => x.kind === "endpoint"); ok(endpoint); - const blobName = client.initialization.properties.find((x) => x.name === "blobName"); + const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); ok(blobName); strictEqual(blobName.clientDefaultValue, undefined); strictEqual(blobName.onClient, true); strictEqual(blobName.optional, false); - const containerName = client.initialization.properties.find( + const containerName = client.initialization.model.properties.find( (x) => x.name === "containerName", ); ok(containerName); @@ -2808,14 +2808,14 @@ describe("typespec-client-generator-core: decorators", () => { const client = sdkPackage.clients[0]; strictEqual(client.initialization.access, "public"); - strictEqual(client.initialization.properties.length, 3); - ok(client.initialization.properties.find((x) => x.kind === "endpoint")); - const blobName = client.initialization.properties.find((x) => x.name === "blobName"); + strictEqual(client.initialization.model.properties.length, 3); + ok(client.initialization.model.properties.find((x) => x.kind === "endpoint")); + const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); ok(blobName); strictEqual(blobName.clientDefaultValue, undefined); strictEqual(blobName.onClient, true); - const containerName = client.initialization.properties.find( + const containerName = client.initialization.model.properties.find( (x) => x.name === "containerName", ); ok(containerName); @@ -2830,10 +2830,10 @@ describe("typespec-client-generator-core: decorators", () => { strictEqual(og.kind, "client"); strictEqual(og.initialization.access, "internal"); - strictEqual(og.initialization.properties.length, 3); - ok(og.initialization.properties.find((x) => x.kind === "endpoint")); - ok(og.initialization.properties.find((x) => x === blobName)); - ok(og.initialization.properties.find((x) => x === containerName)); + strictEqual(og.initialization.model.properties.length, 3); + ok(og.initialization.model.properties.find((x) => x.kind === "endpoint")); + ok(og.initialization.model.properties.find((x) => x === blobName)); + ok(og.initialization.model.properties.find((x) => x === containerName)); const download = og.methods[0]; strictEqual(download.name, "download"); @@ -2889,10 +2889,10 @@ describe("typespec-client-generator-core: decorators", () => { const containerClient = sdkPackage.clients.find((x) => x.name === "ContainerClient"); ok(containerClient); strictEqual(containerClient.initialization.access, "public"); - strictEqual(containerClient.initialization.properties.length, 2); - ok(containerClient.initialization.properties.find((x) => x.kind === "endpoint")); + strictEqual(containerClient.initialization.model.properties.length, 2); + ok(containerClient.initialization.model.properties.find((x) => x.kind === "endpoint")); - const containerName = containerClient.initialization.properties.find( + const containerName = containerClient.initialization.model.properties.find( (x) => x.name === "containerName", ); ok(containerName); @@ -2908,15 +2908,15 @@ describe("typespec-client-generator-core: decorators", () => { const blobClient = sdkPackage.clients.find((x) => x.name === "BlobClient"); ok(blobClient); strictEqual(blobClient.initialization.access, "public"); - strictEqual(blobClient.initialization.properties.length, 3); - ok(blobClient.initialization.properties.find((x) => x.kind === "endpoint")); + strictEqual(blobClient.initialization.model.properties.length, 3); + ok(blobClient.initialization.model.properties.find((x) => x.kind === "endpoint")); - const containerNameOnBlobClient = blobClient.initialization.properties.find( + const containerNameOnBlobClient = blobClient.initialization.model.properties.find( (x) => x.name === "containerName", ); ok(containerNameOnBlobClient); - const blobName = blobClient.initialization.properties.find((x) => x.name === "blobName"); + const blobName = blobClient.initialization.model.properties.find((x) => x.name === "blobName"); ok(blobName); const blobMethods = blobClient.methods; @@ -2954,10 +2954,10 @@ describe("typespec-client-generator-core: decorators", () => { ); const sdkPackage = runner.context.sdkPackage; const client = sdkPackage.clients[0]; - strictEqual(client.initialization.properties.length, 2); - const endpoint = client.initialization.properties.find((x) => x.kind === "endpoint"); + strictEqual(client.initialization.model.properties.length, 2); + const endpoint = client.initialization.model.properties.find((x) => x.kind === "endpoint"); ok(endpoint); - const blobName = client.initialization.properties.find((x) => x.name === "blobName"); + const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); ok(blobName); strictEqual(blobName.clientDefaultValue, undefined); strictEqual(blobName.onClient, true); diff --git a/packages/typespec-client-generator-core/test/package.test.ts b/packages/typespec-client-generator-core/test/package.test.ts index 18e9e006b..01b227bc7 100644 --- a/packages/typespec-client-generator-core/test/package.test.ts +++ b/packages/typespec-client-generator-core/test/package.test.ts @@ -822,12 +822,12 @@ describe("typespec-client-generator-core: package", () => { strictEqual(queryParam.onClient, true); strictEqual( queryParam.correspondingMethodParams[0], - parentClient.initialization.properties.find((x) => x.isApiVersionParam), + parentClient.initialization.model.properties.find((x) => x.isApiVersionParam), ); ok(parentClient.initialization); strictEqual( queryParam.correspondingMethodParams[0], - parentClient.initialization.properties.find((x) => x.isApiVersionParam), + parentClient.initialization.model.properties.find((x) => x.isApiVersionParam), ); const methodAcceptParam = method.parameters.find((x) => x.name === "accept"); @@ -946,7 +946,7 @@ describe("typespec-client-generator-core: package", () => { ok(parentClient.initialization); strictEqual( apiVersionParam.correspondingMethodParams[0], - parentClient.initialization.properties.find((x) => x.isApiVersionParam), + parentClient.initialization.model.properties.find((x) => x.isApiVersionParam), ); const operationAcceptParam = getStatus.operation.parameters.find((x) => x.kind === "header"); @@ -1091,8 +1091,8 @@ describe("typespec-client-generator-core: package", () => { ?.response as SdkClientType; ok(widgetClient); - strictEqual(widgetClient.initialization.properties.length, 3); - const apiVersionClientParam = widgetClient.initialization.properties.find( + strictEqual(widgetClient.initialization.model.properties.length, 3); + const apiVersionClientParam = widgetClient.initialization.model.properties.find( (x) => x.isApiVersionParam, ); ok(apiVersionClientParam); @@ -1225,7 +1225,7 @@ describe("typespec-client-generator-core: package", () => { const sdkPackage = runner.context.sdkPackage; const client = sdkPackage.clients[0].methods.find((x) => x.kind === "clientaccessor") ?.response as SdkClientType; - const apiVersionClientParam = client.initialization.properties.find( + const apiVersionClientParam = client.initialization.model.properties.find( (x) => x.isApiVersionParam, ); ok(apiVersionClientParam); @@ -1275,10 +1275,10 @@ describe("typespec-client-generator-core: package", () => { const sdkPackage = runnerWithArm.context.sdkPackage; const client = sdkPackage.clients[0].methods.find((x) => x.kind === "clientaccessor") ?.response as SdkClientType; - for (const p of client.initialization.properties) { + for (const p of client.initialization.model.properties) { ok(p.onClient); } - deepStrictEqual(client.initialization.properties.map((x) => x.name).sort(), [ + deepStrictEqual(client.initialization.model.properties.map((x) => x.name).sort(), [ "apiVersion", "credential", "endpoint", @@ -1317,7 +1317,7 @@ describe("typespec-client-generator-core: package", () => { strictEqual(apiVersionParam.isApiVersionParam, true); strictEqual(apiVersionParam.clientDefaultValue, "v2"); strictEqual(apiVersionParam.correspondingMethodParams.length, 1); - const clientApiVersionParam = client.initialization.properties.find( + const clientApiVersionParam = client.initialization.model.properties.find( (x) => x.isApiVersionParam, ); ok(clientApiVersionParam); diff --git a/packages/typespec-client-generator-core/test/packages/client.test.ts b/packages/typespec-client-generator-core/test/packages/client.test.ts index a87c529d1..c44fabe43 100644 --- a/packages/typespec-client-generator-core/test/packages/client.test.ts +++ b/packages/typespec-client-generator-core/test/packages/client.test.ts @@ -72,9 +72,9 @@ describe("typespec-client-generator-core: package", () => { strictEqual(sdkPackage.clients.length, 1); const client = sdkPackage.clients[0]; strictEqual(client.name, "ServiceClient"); - strictEqual(client.initialization.name, "ServiceClientOptions"); - strictEqual(client.initialization.properties.length, 1); - const endpointParam = client.initialization.properties[0]; + strictEqual(client.initialization.model.name, "ServiceClientOptions"); + strictEqual(client.initialization.model.properties.length, 1); + const endpointParam = client.initialization.model.properties[0]; strictEqual(endpointParam.kind, "endpoint"); strictEqual(endpointParam.name, "endpoint"); strictEqual(endpointParam.onClient, true); @@ -105,9 +105,9 @@ describe("typespec-client-generator-core: package", () => { strictEqual(sdkPackage.clients.length, 1); const client = sdkPackage.clients[0]; strictEqual(client.name, "ServiceClient"); - strictEqual(client.initialization.properties.length, 2); + strictEqual(client.initialization.model.properties.length, 2); - const endpointParam = client.initialization.properties.filter( + const endpointParam = client.initialization.model.properties.filter( (p): p is SdkEndpointParameter => p.kind === "endpoint", )[0]; strictEqual(endpointParam.type.kind, "endpoint"); @@ -118,7 +118,7 @@ describe("typespec-client-generator-core: package", () => { strictEqual(templateArg.type.kind, "string"); strictEqual(templateArg.clientDefaultValue, "http://localhost:3000"); - const credentialParam = client.initialization.properties.filter( + const credentialParam = client.initialization.model.properties.filter( (p): p is SdkCredentialParameter => p.kind === "credential", )[0]; strictEqual(credentialParam.name, "credential"); @@ -148,9 +148,9 @@ describe("typespec-client-generator-core: package", () => { strictEqual(sdkPackage.clients.length, 1); const client = sdkPackage.clients[0]; strictEqual(client.name, "ServiceClient"); - strictEqual(client.initialization.properties.length, 2); + strictEqual(client.initialization.model.properties.length, 2); - const endpointParam = client.initialization.properties.filter( + const endpointParam = client.initialization.model.properties.filter( (p): p is SdkEndpointParameter => p.kind === "endpoint", )[0]; strictEqual(endpointParam.type.kind, "endpoint"); @@ -163,7 +163,7 @@ describe("typespec-client-generator-core: package", () => { strictEqual(templateArg.onClient, true); strictEqual(templateArg.clientDefaultValue, "http://localhost:3000"); - const credentialParam = client.initialization.properties.filter( + const credentialParam = client.initialization.model.properties.filter( (p): p is SdkCredentialParameter => p.kind === "credential", )[0]; strictEqual(credentialParam.name, "credential"); @@ -199,9 +199,9 @@ describe("typespec-client-generator-core: package", () => { strictEqual(sdkPackage.clients.length, 1); const client = sdkPackage.clients[0]; strictEqual(client.name, "ServiceClient"); - strictEqual(client.initialization.properties.length, 2); + strictEqual(client.initialization.model.properties.length, 2); - const endpointParam = client.initialization.properties.filter( + const endpointParam = client.initialization.model.properties.filter( (p): p is SdkEndpointParameter => p.kind === "endpoint", )[0]; strictEqual(endpointParam.type.kind, "endpoint"); @@ -212,7 +212,7 @@ describe("typespec-client-generator-core: package", () => { strictEqual(templateArg.name, "endpoint"); strictEqual(templateArg.clientDefaultValue, "http://localhost:3000"); - const credentialParam = client.initialization.properties.filter( + const credentialParam = client.initialization.model.properties.filter( (p): p is SdkCredentialParameter => p.kind === "credential", )[0]; strictEqual(credentialParam.name, "credential"); @@ -263,9 +263,9 @@ describe("typespec-client-generator-core: package", () => { strictEqual(sdkPackage.clients.length, 1); const client = sdkPackage.clients[0]; strictEqual(client.name, "ServiceClient"); - strictEqual(client.initialization.properties.length, 2); + strictEqual(client.initialization.model.properties.length, 2); - const endpointParam = client.initialization.properties.filter( + const endpointParam = client.initialization.model.properties.filter( (p): p is SdkEndpointParameter => p.kind === "endpoint", )[0]; strictEqual(endpointParam.clientDefaultValue, undefined); @@ -285,7 +285,7 @@ describe("typespec-client-generator-core: package", () => { strictEqual(templateArg.clientDefaultValue, undefined); strictEqual(templateArg.doc, undefined); - const credentialParam = client.initialization.properties.filter( + const credentialParam = client.initialization.model.properties.filter( (p): p is SdkCredentialParameter => p.kind === "credential", )[0]; strictEqual(credentialParam.name, "credential"); @@ -325,11 +325,11 @@ describe("typespec-client-generator-core: package", () => { strictEqual(sdkPackage.clients.length, 1); const client = sdkPackage.clients[0]; strictEqual(client.name, "ServiceClient"); - strictEqual(client.initialization.properties.length, 2); + strictEqual(client.initialization.model.properties.length, 2); strictEqual(client.apiVersions.length, 1); strictEqual(client.apiVersions[0], "v1.0"); - const endpointParams = client.initialization.properties.filter( + const endpointParams = client.initialization.model.properties.filter( (p): p is SdkEndpointParameter => p.kind === "endpoint", ); strictEqual(endpointParams.length, 1); @@ -374,7 +374,7 @@ describe("typespec-client-generator-core: package", () => { strictEqual(apiVersionParam.kind, "path"); deepStrictEqual(client.apiVersions, ["v1.0"]); - const credentialParam = client.initialization.properties.find( + const credentialParam = client.initialization.model.properties.find( (p): p is SdkCredentialParameter => p.kind === "credential", ); ok(credentialParam); @@ -408,9 +408,9 @@ describe("typespec-client-generator-core: package", () => { strictEqual(sdkPackage.clients.length, 1); const client = sdkPackage.clients[0]; strictEqual(client.name, "ServiceClient"); - strictEqual(client.initialization.properties.length, 1); + strictEqual(client.initialization.model.properties.length, 1); - const endpointParams = client.initialization.properties.filter( + const endpointParams = client.initialization.model.properties.filter( (p): p is SdkEndpointParameter => p.kind === "endpoint", ); strictEqual(endpointParams.length, 1); @@ -470,9 +470,9 @@ describe("typespec-client-generator-core: package", () => { const sdkPackage = runner.context.sdkPackage; strictEqual(sdkPackage.clients.length, 1); const client = sdkPackage.clients[0]; - strictEqual(client.initialization.properties.length, 1); + strictEqual(client.initialization.model.properties.length, 1); - const endpointParam = client.initialization.properties.filter( + const endpointParam = client.initialization.model.properties.filter( (p): p is SdkEndpointParameter => p.kind === "endpoint", )[0]; strictEqual(endpointParam.type.kind, "endpoint"); @@ -530,11 +530,11 @@ describe("typespec-client-generator-core: package", () => { const client = sdkPackage.clients[0]; strictEqual(client.name, "ServiceClient"); strictEqual(client.crossLanguageDefinitionId, "My.Service"); - strictEqual(client.initialization.properties.length, 3); + strictEqual(client.initialization.model.properties.length, 3); strictEqual(client.apiVersions.length, 1); strictEqual(client.apiVersions[0], "2022-12-01-preview"); - const endpointParam = client.initialization.properties.find((x) => x.kind === "endpoint"); + const endpointParam = client.initialization.model.properties.find((x) => x.kind === "endpoint"); ok(endpointParam); strictEqual(endpointParam.name, "endpoint"); strictEqual(endpointParam.kind, "endpoint"); @@ -551,7 +551,7 @@ describe("typespec-client-generator-core: package", () => { strictEqual(endpointTemplateArg.kind, "path"); strictEqual(endpointTemplateArg.clientDefaultValue, "http://localhost:3000"); - const apiVersionParam = client.initialization.properties.filter((p) => p.isApiVersionParam)[0]; + const apiVersionParam = client.initialization.model.properties.filter((p) => p.isApiVersionParam)[0]; strictEqual(apiVersionParam.name, "apiVersion"); strictEqual(apiVersionParam.onClient, true); strictEqual(apiVersionParam.optional, false); @@ -606,11 +606,11 @@ describe("typespec-client-generator-core: package", () => { const client = sdkPackage.clients[0]; strictEqual(client.name, "ServiceClient"); strictEqual(client.crossLanguageDefinitionId, "My.Service"); - strictEqual(client.initialization.properties.length, 3); + strictEqual(client.initialization.model.properties.length, 3); strictEqual(client.apiVersions.length, 2); deepStrictEqual(client.apiVersions, ["2022-12-01-preview", "2022-12-01"]); - const endpointParam = client.initialization.properties.find((x) => x.kind === "endpoint"); + const endpointParam = client.initialization.model.properties.find((x) => x.kind === "endpoint"); ok(endpointParam); strictEqual(endpointParam.type.kind, "endpoint"); strictEqual(endpointParam.type.serverUrl, "{endpoint}"); @@ -621,7 +621,7 @@ describe("typespec-client-generator-core: package", () => { strictEqual(templateArg.onClient, true); strictEqual(templateArg.clientDefaultValue, "http://localhost:3000"); - const apiVersionParam = client.initialization.properties.filter((p) => p.isApiVersionParam)[0]; + const apiVersionParam = client.initialization.model.properties.filter((p) => p.isApiVersionParam)[0]; strictEqual(apiVersionParam.name, "apiVersion"); strictEqual(apiVersionParam.onClient, true); strictEqual(apiVersionParam.optional, false); @@ -672,8 +672,8 @@ describe("typespec-client-generator-core: package", () => { strictEqual(operationGroup.parent, mainClient); strictEqual(mainClient.methods.length, 1); - strictEqual(mainClient.initialization.properties.length, 1); - strictEqual(mainClient.initialization.properties[0].name, "endpoint"); + strictEqual(mainClient.initialization.model.properties.length, 1); + strictEqual(mainClient.initialization.model.properties[0].name, "endpoint"); strictEqual(mainClient.crossLanguageDefinitionId, "TestService"); const clientAccessor = mainClient.methods[0]; @@ -684,7 +684,7 @@ describe("typespec-client-generator-core: package", () => { strictEqual(clientAccessor.response, operationGroup); strictEqual(clientAccessor.crossLanguageDefintionId, "TestService.MyOperationGroup"); - strictEqual(operationGroup.initialization.properties.length, 1); + strictEqual(operationGroup.initialization.model.properties.length, 1); strictEqual(operationGroup.initialization.access, "internal"); strictEqual(operationGroup.methods.length, 1); strictEqual(operationGroup.methods[0].name, "func"); @@ -727,8 +727,8 @@ describe("typespec-client-generator-core: package", () => { strictEqual(mainClient.methods.length, 2); ok(mainClient.initialization); - strictEqual(mainClient.initialization.properties.length, 1); - strictEqual(mainClient.initialization.properties[0].name, "endpoint"); + strictEqual(mainClient.initialization.model.properties.length, 1); + strictEqual(mainClient.initialization.model.properties[0].name, "endpoint"); strictEqual(mainClient.crossLanguageDefinitionId, "TestService"); const fooAccessor = mainClient.methods[0]; @@ -747,7 +747,7 @@ describe("typespec-client-generator-core: package", () => { strictEqual(barAccessor.parameters.length, 0); strictEqual(barAccessor.response, barClient); - strictEqual(fooClient.initialization.properties.length, 1); + strictEqual(fooClient.initialization.model.properties.length, 1); strictEqual(fooClient.initialization.access, "internal"); strictEqual(fooClient.methods.length, 1); strictEqual(fooClient.crossLanguageDefinitionId, "TestService.Foo"); @@ -760,7 +760,7 @@ describe("typespec-client-generator-core: package", () => { strictEqual(fooBarAccessor.parameters.length, 0); strictEqual(fooBarAccessor.response, fooBarClient); - strictEqual(fooBarClient.initialization.properties.length, 1); + strictEqual(fooBarClient.initialization.model.properties.length, 1); strictEqual(fooBarClient.initialization.access, "internal"); strictEqual(fooBarClient.crossLanguageDefinitionId, "TestService.Foo.Bar"); strictEqual(fooBarClient.methods.length, 1); @@ -768,7 +768,7 @@ describe("typespec-client-generator-core: package", () => { strictEqual(fooBarClient.methods[0].name, "one"); strictEqual(fooBarClient.methods[0].crossLanguageDefintionId, "TestService.Foo.Bar.one"); - strictEqual(barClient.initialization.properties.length, 1); + strictEqual(barClient.initialization.model.properties.length, 1); strictEqual(barClient.initialization.access, "internal"); strictEqual(barClient.crossLanguageDefinitionId, "TestService.Bar"); strictEqual(barClient.methods.length, 1); @@ -813,8 +813,8 @@ describe("typespec-client-generator-core: package", () => { strictEqual(sdkPackage.clients.length, 1); const client = sdkPackage.clients[0]; - strictEqual(client.initialization.properties.length, 1); - strictEqual(client.initialization.properties[0].name, "endpoint"); + strictEqual(client.initialization.model.properties.length, 1); + strictEqual(client.initialization.model.properties[0].name, "endpoint"); strictEqual(client.methods.length, 1); @@ -842,8 +842,8 @@ describe("typespec-client-generator-core: package", () => { strictEqual(sdkPackage.clients.length, 1); const client = sdkPackage.clients[0]; - strictEqual(client.initialization.properties.length, 1); - strictEqual(client.initialization.properties[0].name, "endpoint"); + strictEqual(client.initialization.model.properties.length, 1); + strictEqual(client.initialization.model.properties[0].name, "endpoint"); strictEqual(sdkPackage.clients[0].methods.length, 1); const withApiVersion = sdkPackage.clients[0].methods[0]; @@ -887,8 +887,8 @@ describe("typespec-client-generator-core: package", () => { strictEqual(sdkPackage.clients.length, 1); const client = sdkPackage.clients[0]; - strictEqual(client.initialization.properties.length, 1); - strictEqual(client.initialization.properties[0].name, "endpoint"); + strictEqual(client.initialization.model.properties.length, 1); + strictEqual(client.initialization.model.properties[0].name, "endpoint"); const withoutApiVersion = client.methods[0]; strictEqual(withoutApiVersion.kind, "basic"); @@ -917,10 +917,10 @@ describe("typespec-client-generator-core: package", () => { strictEqual(sdkPackage.clients.length, 1); const client = sdkPackage.clients[0]; - strictEqual(client.initialization.properties.length, 2); - strictEqual(client.initialization.properties[0].name, "endpoint"); + strictEqual(client.initialization.model.properties.length, 2); + strictEqual(client.initialization.model.properties[0].name, "endpoint"); - const clientApiVersionParam = client.initialization.properties[1]; + const clientApiVersionParam = client.initialization.model.properties[1]; strictEqual(clientApiVersionParam.name, "apiVersion"); strictEqual(clientApiVersionParam.onClient, true); strictEqual(clientApiVersionParam.optional, false); @@ -950,7 +950,7 @@ describe("typespec-client-generator-core: package", () => { strictEqual(apiVersionParam.correspondingMethodParams.length, 1); strictEqual( apiVersionParam.correspondingMethodParams[0], - client.initialization.properties.find((x) => x.isApiVersionParam), + client.initialization.model.properties.find((x) => x.isApiVersionParam), ); }); @@ -971,10 +971,10 @@ describe("typespec-client-generator-core: package", () => { strictEqual(sdkPackage.clients.length, 1); const client = sdkPackage.clients[0]; - strictEqual(client.initialization.properties.length, 2); - strictEqual(client.initialization.properties[0].name, "endpoint"); + strictEqual(client.initialization.model.properties.length, 2); + strictEqual(client.initialization.model.properties[0].name, "endpoint"); - const clientApiVersionParam = client.initialization.properties[1]; + const clientApiVersionParam = client.initialization.model.properties[1]; strictEqual(clientApiVersionParam.name, "apiVersion"); strictEqual(clientApiVersionParam.onClient, true); strictEqual(clientApiVersionParam.optional, false); @@ -1006,7 +1006,7 @@ describe("typespec-client-generator-core: package", () => { strictEqual(apiVersionParam.correspondingMethodParams.length, 1); strictEqual( apiVersionParam.correspondingMethodParams[0], - client.initialization.properties.find((x) => x.isApiVersionParam), + client.initialization.model.properties.find((x) => x.isApiVersionParam), ); }); @@ -1038,8 +1038,8 @@ describe("typespec-client-generator-core: package", () => { strictEqual(sdkPackage.clients.length, 1); const client = sdkPackage.clients[0]; - strictEqual(client.initialization.properties.length, 1); - const parameter = client.initialization.properties[0]; + strictEqual(client.initialization.model.properties.length, 1); + const parameter = client.initialization.model.properties[0]; strictEqual(parameter.name, "endpoint"); strictEqual(parameter.type.kind, "union"); From 9bb88239a3643916ea68adb84bc6f187bd3ed40b Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Wed, 16 Oct 2024 17:38:21 -0400 Subject: [PATCH 06/11] all tests passing --- packages/typespec-client-generator-core/src/types.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/typespec-client-generator-core/src/types.ts b/packages/typespec-client-generator-core/src/types.ts index 7668bcac8..5cdf51454 100644 --- a/packages/typespec-client-generator-core/src/types.ts +++ b/packages/typespec-client-generator-core/src/types.ts @@ -829,8 +829,10 @@ export function getSdkInitializationType( } for (const prop of initializationModel.model.properties) { - if (!clientParams.filter((p) => p.name === prop.name).length) - clientParams.push(prop); + if (!clientParams.filter((p) => p.name === prop.name).length) { + clientParams.push(prop); + prop.onClient = true; + } } updateUsageOrAccessOfModel(context, UsageFlags.Input, sdkModel, { propagation: false }); updateUsageOrAccessOfModel(context, UsageFlags.ClientInitialization, sdkModel, { From 76b058dfd19bda9527a84e590258b6bb9edf0777 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Wed, 16 Oct 2024 17:43:45 -0400 Subject: [PATCH 07/11] format --- .../src/decorators.ts | 3 -- .../src/package.ts | 40 +++++++++++-------- .../test/decorators.test.ts | 4 +- .../test/packages/client.test.ts | 8 +++- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/packages/typespec-client-generator-core/src/decorators.ts b/packages/typespec-client-generator-core/src/decorators.ts index 74dbb0b1d..df580ba90 100644 --- a/packages/typespec-client-generator-core/src/decorators.ts +++ b/packages/typespec-client-generator-core/src/decorators.ts @@ -52,9 +52,6 @@ import { SdkContext, SdkEmitterOptions, SdkHttpOperation, - SdkInitializationType, - SdkMethodParameter, - SdkModelPropertyType, SdkOperationGroup, SdkServiceOperation, TCGCContext, diff --git a/packages/typespec-client-generator-core/src/package.ts b/packages/typespec-client-generator-core/src/package.ts index b958c1440..2d6d61732 100644 --- a/packages/typespec-client-generator-core/src/package.ts +++ b/packages/typespec-client-generator-core/src/package.ts @@ -427,12 +427,15 @@ function getSdkMethods( const tspClientInitialization = getClientInitialization(context, operationGroup.type); const parameters: SdkParameter[] = []; if (tspClientInitialization) { - const clientInitialization = getSdkInitializationType(context, operationGroup, tspClientInitialization); + const clientInitialization = getSdkInitializationType( + context, + operationGroup, + tspClientInitialization, + ); for (const property of clientInitialization.model.properties) { if (property.kind === "method") { parameters.push(property); } - } } else { } @@ -631,28 +634,33 @@ function addDefaultClientParameters< const diagnostics = createDiagnosticCollector(); // there will always be an endpoint property if (!client.initialization.model.properties.find((x) => x.kind === "endpoint")) { - client.initialization.model.properties.push(diagnostics.pipe(getSdkEndpointParameter(context, client))); + client.initialization.model.properties.push( + diagnostics.pipe(getSdkEndpointParameter(context, client)), + ); } const credentialParam = getSdkCredentialParameter(context, client.__raw); - if (credentialParam && !client.initialization.model.properties.find((x) => x.kind === "credential")) { + if ( + credentialParam && + !client.initialization.model.properties.find((x) => x.kind === "credential") + ) { client.initialization.model.properties.push(credentialParam); } let apiVersionParam = context.__clientToParameters .get(client.__raw.type) ?.find((x) => x.isApiVersionParam); - if (!apiVersionParam) { - for (const operationGroup of listOperationGroups(context, client.__raw)) { - // if any sub operation groups have an api version param, the top level needs - // the api version param as well - apiVersionParam = context.__clientToParameters - .get(operationGroup.type) - ?.find((x) => x.isApiVersionParam); - if (apiVersionParam) break; - } - } - if (apiVersionParam) { - client.initialization.model.properties.push(apiVersionParam); + if (!apiVersionParam) { + for (const operationGroup of listOperationGroups(context, client.__raw)) { + // if any sub operation groups have an api version param, the top level needs + // the api version param as well + apiVersionParam = context.__clientToParameters + .get(operationGroup.type) + ?.find((x) => x.isApiVersionParam); + if (apiVersionParam) break; } + } + if (apiVersionParam) { + client.initialization.model.properties.push(apiVersionParam); + } let subId = context.__clientToParameters .get(client.__raw.type) ?.find((x) => isSubscriptionId(context, x)); diff --git a/packages/typespec-client-generator-core/test/decorators.test.ts b/packages/typespec-client-generator-core/test/decorators.test.ts index 0285b9398..fc1215a20 100644 --- a/packages/typespec-client-generator-core/test/decorators.test.ts +++ b/packages/typespec-client-generator-core/test/decorators.test.ts @@ -2916,7 +2916,9 @@ describe("typespec-client-generator-core: decorators", () => { ); ok(containerNameOnBlobClient); - const blobName = blobClient.initialization.model.properties.find((x) => x.name === "blobName"); + const blobName = blobClient.initialization.model.properties.find( + (x) => x.name === "blobName", + ); ok(blobName); const blobMethods = blobClient.methods; diff --git a/packages/typespec-client-generator-core/test/packages/client.test.ts b/packages/typespec-client-generator-core/test/packages/client.test.ts index c44fabe43..5337eeb99 100644 --- a/packages/typespec-client-generator-core/test/packages/client.test.ts +++ b/packages/typespec-client-generator-core/test/packages/client.test.ts @@ -551,7 +551,9 @@ describe("typespec-client-generator-core: package", () => { strictEqual(endpointTemplateArg.kind, "path"); strictEqual(endpointTemplateArg.clientDefaultValue, "http://localhost:3000"); - const apiVersionParam = client.initialization.model.properties.filter((p) => p.isApiVersionParam)[0]; + const apiVersionParam = client.initialization.model.properties.filter( + (p) => p.isApiVersionParam, + )[0]; strictEqual(apiVersionParam.name, "apiVersion"); strictEqual(apiVersionParam.onClient, true); strictEqual(apiVersionParam.optional, false); @@ -621,7 +623,9 @@ describe("typespec-client-generator-core: package", () => { strictEqual(templateArg.onClient, true); strictEqual(templateArg.clientDefaultValue, "http://localhost:3000"); - const apiVersionParam = client.initialization.model.properties.filter((p) => p.isApiVersionParam)[0]; + const apiVersionParam = client.initialization.model.properties.filter( + (p) => p.isApiVersionParam, + )[0]; strictEqual(apiVersionParam.name, "apiVersion"); strictEqual(apiVersionParam.onClient, true); strictEqual(apiVersionParam.optional, false); From 72c9159fb41a9bb59eb62c9fb68a4b2e1cda881a Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Wed, 16 Oct 2024 17:44:55 -0400 Subject: [PATCH 08/11] add changeset --- ...tcgc-addClientInitializationUsage-2024-9-10-13-12-49.md | 7 ------- ...tcgc-addClientInitializationUsage-2024-9-16-17-44-49.md | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 .chronus/changes/tcgc-addClientInitializationUsage-2024-9-10-13-12-49.md create mode 100644 .chronus/changes/tcgc-addClientInitializationUsage-2024-9-16-17-44-49.md diff --git a/.chronus/changes/tcgc-addClientInitializationUsage-2024-9-10-13-12-49.md b/.chronus/changes/tcgc-addClientInitializationUsage-2024-9-10-13-12-49.md deleted file mode 100644 index 1630c0ad6..000000000 --- a/.chronus/changes/tcgc-addClientInitializationUsage-2024-9-10-13-12-49.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -changeKind: feature -packages: - - "@azure-tools/typespec-client-generator-core" ---- - -git status \ No newline at end of file diff --git a/.chronus/changes/tcgc-addClientInitializationUsage-2024-9-16-17-44-49.md b/.chronus/changes/tcgc-addClientInitializationUsage-2024-9-16-17-44-49.md new file mode 100644 index 000000000..7dab31977 --- /dev/null +++ b/.chronus/changes/tcgc-addClientInitializationUsage-2024-9-16-17-44-49.md @@ -0,0 +1,7 @@ +--- +changeKind: breaking +packages: + - "@azure-tools/typespec-client-generator-core" +--- + +Make `SdkInitializationType` have an `access` property to denote if publicly instantiable, and a `model` property to show the client options model \ No newline at end of file From f9a7f634c3e8a1520d1b0c36b5acae457d212406 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Mon, 21 Oct 2024 17:56:56 -0400 Subject: [PATCH 09/11] address chenjie comments --- .../src/types.ts | 6 +++++- .../test/decorators.test.ts | 21 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/typespec-client-generator-core/src/types.ts b/packages/typespec-client-generator-core/src/types.ts index 5cdf51454..709008723 100644 --- a/packages/typespec-client-generator-core/src/types.ts +++ b/packages/typespec-client-generator-core/src/types.ts @@ -1839,7 +1839,7 @@ export function getAllModelsWithDiagnostics( diagnostics.pipe(updateTypesFromOperation(context, operation)); } const ogs = listOperationGroups(context, client); - const clientInitModel = getClientInitialization(context, client.type); + let clientInitModel = getClientInitialization(context, client.type); if (clientInitModel) { getSdkInitializationType(context, client, clientInitModel); } @@ -1849,6 +1849,10 @@ export function getAllModelsWithDiagnostics( // operations on operation groups diagnostics.pipe(updateTypesFromOperation(context, operation)); } + clientInitModel = getClientInitialization(context, operationGroup!.type); + if (clientInitModel) { + getSdkInitializationType(context, operationGroup!, clientInitModel); + } if (operationGroup?.subOperationGroups) { ogs.push(...operationGroup.subOperationGroups); } diff --git a/packages/typespec-client-generator-core/test/decorators.test.ts b/packages/typespec-client-generator-core/test/decorators.test.ts index fc1215a20..7cf5b552d 100644 --- a/packages/typespec-client-generator-core/test/decorators.test.ts +++ b/packages/typespec-client-generator-core/test/decorators.test.ts @@ -2668,6 +2668,10 @@ describe("typespec-client-generator-core: decorators", () => { strictEqual(blobNameOpParam.correspondingMethodParams.length, 1); strictEqual(blobNameOpParam.correspondingMethodParams[0], blobClientBlobInitializationProp); strictEqual(blobNameOpParam.onClient, true); + + strictEqual(sdkPackage.models.length, 1); + const clientInitializationModel = sdkPackage.models[0]; + ok(clientInitializationModel.usage & UsageFlags.ClientInitialization); }); it("some methods don't have client initialization params", async () => { await runner.compileWithCustomization( @@ -2781,6 +2785,10 @@ describe("typespec-client-generator-core: decorators", () => { strictEqual(containerNameOpParam.name, "containerName"); strictEqual(containerNameOpParam.correspondingMethodParams.length, 1); strictEqual(containerNameOpParam.correspondingMethodParams[0], containerName); + + strictEqual(sdkPackage.models.length, 1); + const clientInitializationModel = sdkPackage.models[0]; + ok(clientInitializationModel.usage & UsageFlags.ClientInitialization); }); it("@operationGroup with same model on parent client", async () => { @@ -2932,6 +2940,19 @@ describe("typespec-client-generator-core: decorators", () => { containerNameOnBlobClient, ); strictEqual(blobMethods[0].operation.parameters[1].correspondingMethodParams[0], blobName); + + strictEqual(sdkPackage.models.length, 2); + const containerClientInitializationModel = sdkPackage.models.find( + (x) => x.name === "ContainerClientInitialization", + ); + ok(containerClientInitializationModel); + ok(containerClientInitializationModel.usage & UsageFlags.ClientInitialization); + + const blobClientInitializationModel = sdkPackage.models.find( + (x) => x.name === "BlobClientInitialization", + ); + ok(blobClientInitializationModel); + ok(blobClientInitializationModel.usage & UsageFlags.ClientInitialization); }); it("@paramAlias", async () => { From fbf5668850049eb0d9f085af86dfa046e3369c72 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Tue, 22 Oct 2024 11:58:18 -0400 Subject: [PATCH 10/11] add test for storage --- .../test/decorators.test.ts | 521 --------------- .../decorators/client-initialization.test.ts | 569 +++++++++++++++++ .../test/decorators/client-name.test.ts | 591 ++++++++++++++++++ 3 files changed, 1160 insertions(+), 521 deletions(-) create mode 100644 packages/typespec-client-generator-core/test/decorators/client-initialization.test.ts create mode 100644 packages/typespec-client-generator-core/test/decorators/client-name.test.ts diff --git a/packages/typespec-client-generator-core/test/decorators.test.ts b/packages/typespec-client-generator-core/test/decorators.test.ts index 7cf5b552d..e01b11f88 100644 --- a/packages/typespec-client-generator-core/test/decorators.test.ts +++ b/packages/typespec-client-generator-core/test/decorators.test.ts @@ -2490,525 +2490,4 @@ describe("typespec-client-generator-core: decorators", () => { strictEqual(paramsParam.type.name, "Params"); }); }); - describe("@clientInitialization", () => { - it("main client", async () => { - await runner.compileWithCustomization( - ` - @service - namespace MyService; - - op download(@path blobName: string): void; - `, - ` - namespace MyCustomizations; - - model MyClientInitialization { - blobName: string; - } - - @@clientInitialization(MyService, MyCustomizations.MyClientInitialization); - `, - ); - const sdkPackage = runner.context.sdkPackage; - const client = sdkPackage.clients[0]; - strictEqual(client.initialization.model.properties.length, 2); - const endpoint = client.initialization.model.properties.find((x) => x.kind === "endpoint"); - ok(endpoint); - const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); - ok(blobName); - strictEqual(blobName.clientDefaultValue, undefined); - strictEqual(blobName.onClient, true); - strictEqual(blobName.optional, false); - - const methods = client.methods; - strictEqual(methods.length, 1); - const download = methods[0]; - strictEqual(download.name, "download"); - strictEqual(download.kind, "basic"); - strictEqual(download.parameters.length, 0); - - const downloadOp = download.operation; - strictEqual(downloadOp.parameters.length, 1); - const blobNameOpParam = downloadOp.parameters[0]; - strictEqual(blobNameOpParam.name, "blobName"); - strictEqual(blobNameOpParam.correspondingMethodParams.length, 1); - strictEqual(blobNameOpParam.correspondingMethodParams[0], blobName); - strictEqual(blobNameOpParam.onClient, true); - - strictEqual(sdkPackage.models.length, 1); - const clientInitializationModel = sdkPackage.models[0]; - ok(clientInitializationModel.usage & UsageFlags.ClientInitialization); - }); - - it("On Interface", async () => { - await runner.compileWithBuiltInService( - ` - model clientInitModel - { - p1: string; - } - - @route("/bump") - @clientInitialization(clientInitModel) - interface bumpParameter { - @route("/op1") - @doc("bump parameter") - @post - @convenientAPI(true) - op op1(@path p1: string, @query q1: string): void; - - @route("/op2") - @doc("bump parameter") - @post - @convenientAPI(true) - op op2(@path p1: string): void; - } - `, - ); - const sdkPackage = runner.context.sdkPackage; - const clientAccessor = sdkPackage.clients[0].methods[0]; - strictEqual(clientAccessor.kind, "clientaccessor"); - const bumpParameterClient = clientAccessor.response; - - const methods = bumpParameterClient.methods; - strictEqual(methods.length, 2); - - const op1Method = methods.find((x) => x.name === "op1"); - ok(op1Method); - strictEqual(op1Method.kind, "basic"); - strictEqual(op1Method.parameters.length, 1); - strictEqual(op1Method.parameters[0].name, "q1"); - const op1Op = op1Method.operation; - strictEqual(op1Op.parameters.length, 2); - strictEqual(op1Op.parameters[0].name, "p1"); - strictEqual(op1Op.parameters[0].onClient, true); - strictEqual(op1Op.parameters[1].name, "q1"); - strictEqual(op1Op.parameters[1].onClient, false); - }); - it("subclient", async () => { - await runner.compileWithCustomization( - ` - @service - namespace StorageClient { - - @route("/main") - op download(@path blobName: string): void; - - interface BlobClient { - @route("/blob") - op download(@path blobName: string): void; - } - } - `, - ` - model ClientInitialization { - blobName: string - }; - - @@clientInitialization(StorageClient, ClientInitialization); - @@clientInitialization(StorageClient.BlobClient, ClientInitialization); - `, - ); - const sdkPackage = runner.context.sdkPackage; - const clients = sdkPackage.clients; - strictEqual(clients.length, 1); - const client = clients[0]; - strictEqual(client.name, "StorageClient"); - strictEqual(client.initialization.access, "public"); - strictEqual(client.initialization.model.properties.length, 2); - ok(client.initialization.model.properties.find((x) => x.kind === "endpoint")); - const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); - ok(blobName); - strictEqual(blobName.onClient, true); - - const methods = client.methods; - strictEqual(methods.length, 2); - - // the main client's function should not have `blobName` as a client method parameter - const mainClientDownload = methods.find((x) => x.kind === "basic" && x.name === "download"); - ok(mainClientDownload); - strictEqual(mainClientDownload.parameters.length, 0); - - const getBlobClient = methods.find((x) => x.kind === "clientaccessor"); - ok(getBlobClient); - strictEqual(getBlobClient.kind, "clientaccessor"); - strictEqual(getBlobClient.name, "getBlobClient"); - strictEqual(getBlobClient.parameters.length, 1); - const blobNameParam = getBlobClient.parameters.find((x) => x.name === "blobName"); - ok(blobNameParam); - strictEqual(blobNameParam.onClient, true); - strictEqual(blobNameParam.optional, false); - strictEqual(blobNameParam.kind, "method"); - - const blobClient = getBlobClient.response; - - strictEqual(blobClient.kind, "client"); - strictEqual(blobClient.name, "BlobClient"); - strictEqual(blobClient.initialization.access, "internal"); - strictEqual(blobClient.initialization.model.properties.length, 2); - - ok(blobClient.initialization.model.properties.find((x) => x.kind === "endpoint")); - const blobClientBlobInitializationProp = blobClient.initialization.model.properties.find( - (x) => x.name === "blobName", - ); - ok(blobClientBlobInitializationProp); - strictEqual(blobClientBlobInitializationProp.kind, "method"); - strictEqual(blobClientBlobInitializationProp.onClient, true); - strictEqual(blobClient.methods.length, 1); - - const download = blobClient.methods[0]; - strictEqual(download.name, "download"); - strictEqual(download.kind, "basic"); - strictEqual(download.parameters.length, 0); - - const downloadOp = download.operation; - strictEqual(downloadOp.parameters.length, 1); - const blobNameOpParam = downloadOp.parameters[0]; - strictEqual(blobNameOpParam.name, "blobName"); - strictEqual(blobNameOpParam.correspondingMethodParams.length, 1); - strictEqual(blobNameOpParam.correspondingMethodParams[0], blobClientBlobInitializationProp); - strictEqual(blobNameOpParam.onClient, true); - - strictEqual(sdkPackage.models.length, 1); - const clientInitializationModel = sdkPackage.models[0]; - ok(clientInitializationModel.usage & UsageFlags.ClientInitialization); - }); - it("some methods don't have client initialization params", async () => { - await runner.compileWithCustomization( - ` - @service - namespace MyService; - - op download(@path blobName: string, @header header: int32): void; - op noClientParams(@query query: int32): void; - `, - ` - namespace MyCustomizations; - - model MyClientInitialization { - blobName: string; - } - - @@clientInitialization(MyService, MyCustomizations.MyClientInitialization); - `, - ); - const sdkPackage = runner.context.sdkPackage; - const client = sdkPackage.clients[0]; - strictEqual(client.initialization.model.properties.length, 2); - const endpoint = client.initialization.model.properties.find((x) => x.kind === "endpoint"); - ok(endpoint); - const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); - ok(blobName); - strictEqual(blobName.clientDefaultValue, undefined); - strictEqual(blobName.onClient, true); - strictEqual(blobName.optional, false); - - const methods = client.methods; - strictEqual(methods.length, 2); - const download = methods[0]; - strictEqual(download.name, "download"); - strictEqual(download.kind, "basic"); - strictEqual(download.parameters.length, 1); - - const headerParam = download.parameters.find((x) => x.name === "header"); - ok(headerParam); - strictEqual(headerParam.onClient, false); - - const downloadOp = download.operation; - strictEqual(downloadOp.parameters.length, 2); - const blobNameOpParam = downloadOp.parameters[0]; - strictEqual(blobNameOpParam.name, "blobName"); - strictEqual(blobNameOpParam.correspondingMethodParams.length, 1); - strictEqual(blobNameOpParam.correspondingMethodParams[0], blobName); - strictEqual(blobNameOpParam.onClient, true); - - const noClientParamsMethod = methods[1]; - strictEqual(noClientParamsMethod.name, "noClientParams"); - strictEqual(noClientParamsMethod.kind, "basic"); - strictEqual(noClientParamsMethod.parameters.length, 1); - strictEqual(noClientParamsMethod.parameters[0].name, "query"); - strictEqual(noClientParamsMethod.parameters[0].onClient, false); - }); - - it("multiple client params", async () => { - await runner.compileWithCustomization( - ` - @service - namespace MyService; - - op download(@path blobName: string, @path containerName: string): void; - `, - ` - namespace MyCustomizations; - - model MyClientInitialization { - blobName: string; - containerName: string; - } - - @@clientInitialization(MyService, MyCustomizations.MyClientInitialization); - `, - ); - const sdkPackage = runner.context.sdkPackage; - const client = sdkPackage.clients[0]; - strictEqual(client.initialization.model.properties.length, 3); - const endpoint = client.initialization.model.properties.find((x) => x.kind === "endpoint"); - ok(endpoint); - const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); - ok(blobName); - strictEqual(blobName.clientDefaultValue, undefined); - strictEqual(blobName.onClient, true); - strictEqual(blobName.optional, false); - - const containerName = client.initialization.model.properties.find( - (x) => x.name === "containerName", - ); - ok(containerName); - strictEqual(containerName.clientDefaultValue, undefined); - strictEqual(containerName.onClient, true); - - const methods = client.methods; - strictEqual(methods.length, 1); - const download = methods[0]; - strictEqual(download.name, "download"); - strictEqual(download.kind, "basic"); - strictEqual(download.parameters.length, 0); - - const downloadOp = download.operation; - strictEqual(downloadOp.parameters.length, 2); - const blobNameOpParam = downloadOp.parameters[0]; - strictEqual(blobNameOpParam.name, "blobName"); - strictEqual(blobNameOpParam.correspondingMethodParams.length, 1); - strictEqual(blobNameOpParam.correspondingMethodParams[0], blobName); - - const containerNameOpParam = downloadOp.parameters[1]; - strictEqual(containerNameOpParam.name, "containerName"); - strictEqual(containerNameOpParam.correspondingMethodParams.length, 1); - strictEqual(containerNameOpParam.correspondingMethodParams[0], containerName); - - strictEqual(sdkPackage.models.length, 1); - const clientInitializationModel = sdkPackage.models[0]; - ok(clientInitializationModel.usage & UsageFlags.ClientInitialization); - }); - - it("@operationGroup with same model on parent client", async () => { - await runner.compile( - ` - @service - namespace MyService; - - @operationGroup - interface MyInterface { - op download(@path blobName: string, @path containerName: string): void; - } - - model MyClientInitialization { - blobName: string; - containerName: string; - } - - @@clientInitialization(MyService, MyClientInitialization); - @@clientInitialization(MyService.MyInterface, MyClientInitialization); - `, - ); - const sdkPackage = runner.context.sdkPackage; - strictEqual(sdkPackage.clients.length, 1); - - const client = sdkPackage.clients[0]; - strictEqual(client.initialization.access, "public"); - strictEqual(client.initialization.model.properties.length, 3); - ok(client.initialization.model.properties.find((x) => x.kind === "endpoint")); - const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); - ok(blobName); - strictEqual(blobName.clientDefaultValue, undefined); - strictEqual(blobName.onClient, true); - - const containerName = client.initialization.model.properties.find( - (x) => x.name === "containerName", - ); - ok(containerName); - strictEqual(containerName.clientDefaultValue, undefined); - strictEqual(containerName.onClient, true); - - const methods = client.methods; - strictEqual(methods.length, 1); - const clientAccessor = methods[0]; - strictEqual(clientAccessor.kind, "clientaccessor"); - const og = clientAccessor.response; - strictEqual(og.kind, "client"); - - strictEqual(og.initialization.access, "internal"); - strictEqual(og.initialization.model.properties.length, 3); - ok(og.initialization.model.properties.find((x) => x.kind === "endpoint")); - ok(og.initialization.model.properties.find((x) => x === blobName)); - ok(og.initialization.model.properties.find((x) => x === containerName)); - - const download = og.methods[0]; - strictEqual(download.name, "download"); - strictEqual(download.kind, "basic"); - strictEqual(download.parameters.length, 0); - - const op = download.operation; - strictEqual(op.parameters.length, 2); - strictEqual(op.parameters[0].correspondingMethodParams[0], blobName); - strictEqual(op.parameters[1].correspondingMethodParams[0], containerName); - strictEqual(op.parameters[0].onClient, true); - strictEqual(op.parameters[1].onClient, true); - }); - - it("redefine client structure", async () => { - await runner.compileWithCustomization( - ` - @service - namespace MyService; - - op uploadContainer(@path containerName: string): void; - op uploadBlob(@path containerName: string, @path blobName: string): void; - `, - ` - namespace MyCustomizations { - model ContainerClientInitialization { - containerName: string; - } - @client({service: MyService}) - @clientInitialization(ContainerClientInitialization) - namespace ContainerClient { - op upload is MyService.uploadContainer; - - - model BlobClientInitialization { - containerName: string; - blobName: string; - } - - @client({service: MyService}) - @clientInitialization(BlobClientInitialization) - namespace BlobClient { - op upload is MyService.uploadBlob; - } - } - } - - `, - ); - const sdkPackage = runner.context.sdkPackage; - strictEqual(sdkPackage.clients.length, 2); - - const containerClient = sdkPackage.clients.find((x) => x.name === "ContainerClient"); - ok(containerClient); - strictEqual(containerClient.initialization.access, "public"); - strictEqual(containerClient.initialization.model.properties.length, 2); - ok(containerClient.initialization.model.properties.find((x) => x.kind === "endpoint")); - - const containerName = containerClient.initialization.model.properties.find( - (x) => x.name === "containerName", - ); - ok(containerName); - - const methods = containerClient.methods; - strictEqual(methods.length, 1); - strictEqual(methods[0].name, "upload"); - strictEqual(methods[0].kind, "basic"); - strictEqual(methods[0].parameters.length, 0); - strictEqual(methods[0].operation.parameters.length, 1); - strictEqual(methods[0].operation.parameters[0].correspondingMethodParams[0], containerName); - - const blobClient = sdkPackage.clients.find((x) => x.name === "BlobClient"); - ok(blobClient); - strictEqual(blobClient.initialization.access, "public"); - strictEqual(blobClient.initialization.model.properties.length, 3); - ok(blobClient.initialization.model.properties.find((x) => x.kind === "endpoint")); - - const containerNameOnBlobClient = blobClient.initialization.model.properties.find( - (x) => x.name === "containerName", - ); - ok(containerNameOnBlobClient); - - const blobName = blobClient.initialization.model.properties.find( - (x) => x.name === "blobName", - ); - ok(blobName); - - const blobMethods = blobClient.methods; - strictEqual(blobMethods.length, 1); - strictEqual(blobMethods[0].name, "upload"); - strictEqual(blobMethods[0].kind, "basic"); - strictEqual(blobMethods[0].parameters.length, 0); - strictEqual(blobMethods[0].operation.parameters.length, 2); - strictEqual( - blobMethods[0].operation.parameters[0].correspondingMethodParams[0], - containerNameOnBlobClient, - ); - strictEqual(blobMethods[0].operation.parameters[1].correspondingMethodParams[0], blobName); - - strictEqual(sdkPackage.models.length, 2); - const containerClientInitializationModel = sdkPackage.models.find( - (x) => x.name === "ContainerClientInitialization", - ); - ok(containerClientInitializationModel); - ok(containerClientInitializationModel.usage & UsageFlags.ClientInitialization); - - const blobClientInitializationModel = sdkPackage.models.find( - (x) => x.name === "BlobClientInitialization", - ); - ok(blobClientInitializationModel); - ok(blobClientInitializationModel.usage & UsageFlags.ClientInitialization); - }); - - it("@paramAlias", async () => { - await runner.compileWithCustomization( - ` - @service - namespace MyService; - - op download(@path blob: string): void; - op upload(@path blobName: string): void; - `, - ` - namespace MyCustomizations; - - model MyClientInitialization { - @paramAlias("blob") - blobName: string; - } - - @@clientInitialization(MyService, MyCustomizations.MyClientInitialization); - `, - ); - const sdkPackage = runner.context.sdkPackage; - const client = sdkPackage.clients[0]; - strictEqual(client.initialization.model.properties.length, 2); - const endpoint = client.initialization.model.properties.find((x) => x.kind === "endpoint"); - ok(endpoint); - const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); - ok(blobName); - strictEqual(blobName.clientDefaultValue, undefined); - strictEqual(blobName.onClient, true); - strictEqual(blobName.optional, false); - - const methods = client.methods; - strictEqual(methods.length, 2); - const download = methods[0]; - strictEqual(download.name, "download"); - strictEqual(download.kind, "basic"); - strictEqual(download.parameters.length, 0); - - const downloadOp = download.operation; - strictEqual(downloadOp.parameters.length, 1); - strictEqual(downloadOp.parameters[0].name, "blob"); - strictEqual(downloadOp.parameters[0].correspondingMethodParams.length, 1); - strictEqual(downloadOp.parameters[0].correspondingMethodParams[0], blobName); - - const upload = methods[1]; - strictEqual(upload.name, "upload"); - strictEqual(upload.kind, "basic"); - strictEqual(upload.parameters.length, 0); - - const uploadOp = upload.operation; - strictEqual(uploadOp.parameters.length, 1); - strictEqual(uploadOp.parameters[0].name, "blobName"); - strictEqual(uploadOp.parameters[0].correspondingMethodParams.length, 1); - strictEqual(uploadOp.parameters[0].correspondingMethodParams[0], blobName); - }); - }); }); diff --git a/packages/typespec-client-generator-core/test/decorators/client-initialization.test.ts b/packages/typespec-client-generator-core/test/decorators/client-initialization.test.ts new file mode 100644 index 000000000..2a1daf23f --- /dev/null +++ b/packages/typespec-client-generator-core/test/decorators/client-initialization.test.ts @@ -0,0 +1,569 @@ +import { ok, strictEqual } from "assert"; +import { beforeEach, describe, it } from "vitest"; +import { UsageFlags } from "../../src/interfaces.js"; +import { SdkTestRunner, createSdkTestRunner } from "../test-host.js"; + +describe("@clientInitialization", () => { + let runner: SdkTestRunner; + + beforeEach(async () => { + runner = await createSdkTestRunner({ emitterName: "@azure-tools/typespec-python" }); + }); + + it("main client", async () => { + await runner.compileWithCustomization( + ` + @service + namespace MyService; + + op download(@path blobName: string): void; + `, + ` + namespace MyCustomizations; + + model MyClientInitialization { + blobName: string; + } + + @@clientInitialization(MyService, MyCustomizations.MyClientInitialization); + `, + ); + const sdkPackage = runner.context.sdkPackage; + const client = sdkPackage.clients[0]; + strictEqual(client.initialization.model.properties.length, 2); + const endpoint = client.initialization.model.properties.find((x) => x.kind === "endpoint"); + ok(endpoint); + const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); + ok(blobName); + strictEqual(blobName.clientDefaultValue, undefined); + strictEqual(blobName.onClient, true); + strictEqual(blobName.optional, false); + + const methods = client.methods; + strictEqual(methods.length, 1); + const download = methods[0]; + strictEqual(download.name, "download"); + strictEqual(download.kind, "basic"); + strictEqual(download.parameters.length, 0); + + const downloadOp = download.operation; + strictEqual(downloadOp.parameters.length, 1); + const blobNameOpParam = downloadOp.parameters[0]; + strictEqual(blobNameOpParam.name, "blobName"); + strictEqual(blobNameOpParam.correspondingMethodParams.length, 1); + strictEqual(blobNameOpParam.correspondingMethodParams[0], blobName); + strictEqual(blobNameOpParam.onClient, true); + + strictEqual(sdkPackage.models.length, 1); + const clientInitializationModel = sdkPackage.models[0]; + ok(clientInitializationModel.usage & UsageFlags.ClientInitialization); + }); + + it("On Interface", async () => { + await runner.compileWithBuiltInService( + ` + model clientInitModel + { + p1: string; + } + + @route("/bump") + @clientInitialization(clientInitModel) + interface bumpParameter { + @route("/op1") + @doc("bump parameter") + @post + @convenientAPI(true) + op op1(@path p1: string, @query q1: string): void; + + @route("/op2") + @doc("bump parameter") + @post + @convenientAPI(true) + op op2(@path p1: string): void; + } + `, + ); + const sdkPackage = runner.context.sdkPackage; + const clientAccessor = sdkPackage.clients[0].methods[0]; + strictEqual(clientAccessor.kind, "clientaccessor"); + const bumpParameterClient = clientAccessor.response; + + const methods = bumpParameterClient.methods; + strictEqual(methods.length, 2); + + const op1Method = methods.find((x) => x.name === "op1"); + ok(op1Method); + strictEqual(op1Method.kind, "basic"); + strictEqual(op1Method.parameters.length, 1); + strictEqual(op1Method.parameters[0].name, "q1"); + const op1Op = op1Method.operation; + strictEqual(op1Op.parameters.length, 2); + strictEqual(op1Op.parameters[0].name, "p1"); + strictEqual(op1Op.parameters[0].onClient, true); + strictEqual(op1Op.parameters[1].name, "q1"); + strictEqual(op1Op.parameters[1].onClient, false); + }); + it("subclient", async () => { + await runner.compileWithCustomization( + ` + @service + namespace StorageClient { + + @route("/main") + op download(@path blobName: string): void; + + interface BlobClient { + @route("/blob") + op download(@path blobName: string): void; + } + } + `, + ` + model ClientInitialization { + blobName: string + }; + + @@clientInitialization(StorageClient, ClientInitialization); + @@clientInitialization(StorageClient.BlobClient, ClientInitialization); + `, + ); + const sdkPackage = runner.context.sdkPackage; + const clients = sdkPackage.clients; + strictEqual(clients.length, 1); + const client = clients[0]; + strictEqual(client.name, "StorageClient"); + strictEqual(client.initialization.access, "public"); + strictEqual(client.initialization.model.properties.length, 2); + ok(client.initialization.model.properties.find((x) => x.kind === "endpoint")); + const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); + ok(blobName); + strictEqual(blobName.onClient, true); + + const methods = client.methods; + strictEqual(methods.length, 2); + + // the main client's function should not have `blobName` as a client method parameter + const mainClientDownload = methods.find((x) => x.kind === "basic" && x.name === "download"); + ok(mainClientDownload); + strictEqual(mainClientDownload.parameters.length, 0); + + const getBlobClient = methods.find((x) => x.kind === "clientaccessor"); + ok(getBlobClient); + strictEqual(getBlobClient.kind, "clientaccessor"); + strictEqual(getBlobClient.name, "getBlobClient"); + strictEqual(getBlobClient.parameters.length, 1); + const blobNameParam = getBlobClient.parameters.find((x) => x.name === "blobName"); + ok(blobNameParam); + strictEqual(blobNameParam.onClient, true); + strictEqual(blobNameParam.optional, false); + strictEqual(blobNameParam.kind, "method"); + + const blobClient = getBlobClient.response; + + strictEqual(blobClient.kind, "client"); + strictEqual(blobClient.name, "BlobClient"); + strictEqual(blobClient.initialization.access, "internal"); + strictEqual(blobClient.initialization.model.properties.length, 2); + + ok(blobClient.initialization.model.properties.find((x) => x.kind === "endpoint")); + const blobClientBlobInitializationProp = blobClient.initialization.model.properties.find( + (x) => x.name === "blobName", + ); + ok(blobClientBlobInitializationProp); + strictEqual(blobClientBlobInitializationProp.kind, "method"); + strictEqual(blobClientBlobInitializationProp.onClient, true); + strictEqual(blobClient.methods.length, 1); + + const download = blobClient.methods[0]; + strictEqual(download.name, "download"); + strictEqual(download.kind, "basic"); + strictEqual(download.parameters.length, 0); + + const downloadOp = download.operation; + strictEqual(downloadOp.parameters.length, 1); + const blobNameOpParam = downloadOp.parameters[0]; + strictEqual(blobNameOpParam.name, "blobName"); + strictEqual(blobNameOpParam.correspondingMethodParams.length, 1); + strictEqual(blobNameOpParam.correspondingMethodParams[0], blobClientBlobInitializationProp); + strictEqual(blobNameOpParam.onClient, true); + + strictEqual(sdkPackage.models.length, 1); + const clientInitializationModel = sdkPackage.models[0]; + ok(clientInitializationModel.usage & UsageFlags.ClientInitialization); + }); + it("some methods don't have client initialization params", async () => { + await runner.compileWithCustomization( + ` + @service + namespace MyService; + + op download(@path blobName: string, @header header: int32): void; + op noClientParams(@query query: int32): void; + `, + ` + namespace MyCustomizations; + + model MyClientInitialization { + blobName: string; + } + + @@clientInitialization(MyService, MyCustomizations.MyClientInitialization); + `, + ); + const sdkPackage = runner.context.sdkPackage; + const client = sdkPackage.clients[0]; + strictEqual(client.initialization.model.properties.length, 2); + const endpoint = client.initialization.model.properties.find((x) => x.kind === "endpoint"); + ok(endpoint); + const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); + ok(blobName); + strictEqual(blobName.clientDefaultValue, undefined); + strictEqual(blobName.onClient, true); + strictEqual(blobName.optional, false); + + const methods = client.methods; + strictEqual(methods.length, 2); + const download = methods[0]; + strictEqual(download.name, "download"); + strictEqual(download.kind, "basic"); + strictEqual(download.parameters.length, 1); + + const headerParam = download.parameters.find((x) => x.name === "header"); + ok(headerParam); + strictEqual(headerParam.onClient, false); + + const downloadOp = download.operation; + strictEqual(downloadOp.parameters.length, 2); + const blobNameOpParam = downloadOp.parameters[0]; + strictEqual(blobNameOpParam.name, "blobName"); + strictEqual(blobNameOpParam.correspondingMethodParams.length, 1); + strictEqual(blobNameOpParam.correspondingMethodParams[0], blobName); + strictEqual(blobNameOpParam.onClient, true); + + const noClientParamsMethod = methods[1]; + strictEqual(noClientParamsMethod.name, "noClientParams"); + strictEqual(noClientParamsMethod.kind, "basic"); + strictEqual(noClientParamsMethod.parameters.length, 1); + strictEqual(noClientParamsMethod.parameters[0].name, "query"); + strictEqual(noClientParamsMethod.parameters[0].onClient, false); + }); + + it("multiple client params", async () => { + await runner.compileWithCustomization( + ` + @service + namespace MyService; + + op download(@path blobName: string, @path containerName: string): void; + `, + ` + namespace MyCustomizations; + + model MyClientInitialization { + blobName: string; + containerName: string; + } + + @@clientInitialization(MyService, MyCustomizations.MyClientInitialization); + `, + ); + const sdkPackage = runner.context.sdkPackage; + const client = sdkPackage.clients[0]; + strictEqual(client.initialization.model.properties.length, 3); + const endpoint = client.initialization.model.properties.find((x) => x.kind === "endpoint"); + ok(endpoint); + const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); + ok(blobName); + strictEqual(blobName.clientDefaultValue, undefined); + strictEqual(blobName.onClient, true); + strictEqual(blobName.optional, false); + + const containerName = client.initialization.model.properties.find( + (x) => x.name === "containerName", + ); + ok(containerName); + strictEqual(containerName.clientDefaultValue, undefined); + strictEqual(containerName.onClient, true); + + const methods = client.methods; + strictEqual(methods.length, 1); + const download = methods[0]; + strictEqual(download.name, "download"); + strictEqual(download.kind, "basic"); + strictEqual(download.parameters.length, 0); + + const downloadOp = download.operation; + strictEqual(downloadOp.parameters.length, 2); + const blobNameOpParam = downloadOp.parameters[0]; + strictEqual(blobNameOpParam.name, "blobName"); + strictEqual(blobNameOpParam.correspondingMethodParams.length, 1); + strictEqual(blobNameOpParam.correspondingMethodParams[0], blobName); + + const containerNameOpParam = downloadOp.parameters[1]; + strictEqual(containerNameOpParam.name, "containerName"); + strictEqual(containerNameOpParam.correspondingMethodParams.length, 1); + strictEqual(containerNameOpParam.correspondingMethodParams[0], containerName); + + strictEqual(sdkPackage.models.length, 1); + const clientInitializationModel = sdkPackage.models[0]; + ok(clientInitializationModel.usage & UsageFlags.ClientInitialization); + }); + + it("@operationGroup with same model on parent client", async () => { + await runner.compile( + ` + @service + namespace MyService; + + @operationGroup + interface MyInterface { + op download(@path blobName: string, @path containerName: string): void; + } + + model MyClientInitialization { + blobName: string; + containerName: string; + } + + @@clientInitialization(MyService, MyClientInitialization); + @@clientInitialization(MyService.MyInterface, MyClientInitialization); + `, + ); + const sdkPackage = runner.context.sdkPackage; + strictEqual(sdkPackage.clients.length, 1); + + const client = sdkPackage.clients[0]; + strictEqual(client.initialization.access, "public"); + strictEqual(client.initialization.model.properties.length, 3); + ok(client.initialization.model.properties.find((x) => x.kind === "endpoint")); + const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); + ok(blobName); + strictEqual(blobName.clientDefaultValue, undefined); + strictEqual(blobName.onClient, true); + + const containerName = client.initialization.model.properties.find( + (x) => x.name === "containerName", + ); + ok(containerName); + strictEqual(containerName.clientDefaultValue, undefined); + strictEqual(containerName.onClient, true); + + const methods = client.methods; + strictEqual(methods.length, 1); + const clientAccessor = methods[0]; + strictEqual(clientAccessor.kind, "clientaccessor"); + const og = clientAccessor.response; + strictEqual(og.kind, "client"); + + strictEqual(og.initialization.access, "internal"); + strictEqual(og.initialization.model.properties.length, 3); + ok(og.initialization.model.properties.find((x) => x.kind === "endpoint")); + ok(og.initialization.model.properties.find((x) => x === blobName)); + ok(og.initialization.model.properties.find((x) => x === containerName)); + + const download = og.methods[0]; + strictEqual(download.name, "download"); + strictEqual(download.kind, "basic"); + strictEqual(download.parameters.length, 0); + + const op = download.operation; + strictEqual(op.parameters.length, 2); + strictEqual(op.parameters[0].correspondingMethodParams[0], blobName); + strictEqual(op.parameters[1].correspondingMethodParams[0], containerName); + strictEqual(op.parameters[0].onClient, true); + strictEqual(op.parameters[1].onClient, true); + }); + + it("redefine client structure", async () => { + await runner.compileWithCustomization( + ` + @service + namespace MyService; + + op uploadContainer(@path containerName: string): void; + op uploadBlob(@path containerName: string, @path blobName: string): void; + `, + ` + namespace MyCustomizations { + model ContainerClientInitialization { + containerName: string; + } + @client({service: MyService}) + @clientInitialization(ContainerClientInitialization) + namespace ContainerClient { + op upload is MyService.uploadContainer; + + + model BlobClientInitialization { + containerName: string; + blobName: string; + } + + @client({service: MyService}) + @clientInitialization(BlobClientInitialization) + namespace BlobClient { + op upload is MyService.uploadBlob; + } + } + } + + `, + ); + const sdkPackage = runner.context.sdkPackage; + strictEqual(sdkPackage.clients.length, 2); + + const containerClient = sdkPackage.clients.find((x) => x.name === "ContainerClient"); + ok(containerClient); + strictEqual(containerClient.initialization.access, "public"); + strictEqual(containerClient.initialization.model.properties.length, 2); + ok(containerClient.initialization.model.properties.find((x) => x.kind === "endpoint")); + + const containerName = containerClient.initialization.model.properties.find( + (x) => x.name === "containerName", + ); + ok(containerName); + + const methods = containerClient.methods; + strictEqual(methods.length, 1); + strictEqual(methods[0].name, "upload"); + strictEqual(methods[0].kind, "basic"); + strictEqual(methods[0].parameters.length, 0); + strictEqual(methods[0].operation.parameters.length, 1); + strictEqual(methods[0].operation.parameters[0].correspondingMethodParams[0], containerName); + + const blobClient = sdkPackage.clients.find((x) => x.name === "BlobClient"); + ok(blobClient); + strictEqual(blobClient.initialization.access, "public"); + strictEqual(blobClient.initialization.model.properties.length, 3); + ok(blobClient.initialization.model.properties.find((x) => x.kind === "endpoint")); + + const containerNameOnBlobClient = blobClient.initialization.model.properties.find( + (x) => x.name === "containerName", + ); + ok(containerNameOnBlobClient); + + const blobName = blobClient.initialization.model.properties.find((x) => x.name === "blobName"); + ok(blobName); + + const blobMethods = blobClient.methods; + strictEqual(blobMethods.length, 1); + strictEqual(blobMethods[0].name, "upload"); + strictEqual(blobMethods[0].kind, "basic"); + strictEqual(blobMethods[0].parameters.length, 0); + strictEqual(blobMethods[0].operation.parameters.length, 2); + strictEqual( + blobMethods[0].operation.parameters[0].correspondingMethodParams[0], + containerNameOnBlobClient, + ); + strictEqual(blobMethods[0].operation.parameters[1].correspondingMethodParams[0], blobName); + + strictEqual(sdkPackage.models.length, 2); + const containerClientInitializationModel = sdkPackage.models.find( + (x) => x.name === "ContainerClientInitialization", + ); + ok(containerClientInitializationModel); + ok(containerClientInitializationModel.usage & UsageFlags.ClientInitialization); + + const blobClientInitializationModel = sdkPackage.models.find( + (x) => x.name === "BlobClientInitialization", + ); + ok(blobClientInitializationModel); + ok(blobClientInitializationModel.usage & UsageFlags.ClientInitialization); + }); + + it("@paramAlias", async () => { + await runner.compileWithCustomization( + ` + @service + namespace MyService; + + op download(@path blob: string): void; + op upload(@path blobName: string): void; + `, + ` + namespace MyCustomizations; + + model MyClientInitialization { + @paramAlias("blob") + blobName: string; + } + + @@clientInitialization(MyService, MyCustomizations.MyClientInitialization); + `, + ); + const sdkPackage = runner.context.sdkPackage; + const client = sdkPackage.clients[0]; + strictEqual(client.initialization.model.properties.length, 2); + const endpoint = client.initialization.model.properties.find((x) => x.kind === "endpoint"); + ok(endpoint); + const blobName = client.initialization.model.properties.find((x) => x.name === "blobName"); + ok(blobName); + strictEqual(blobName.clientDefaultValue, undefined); + strictEqual(blobName.onClient, true); + strictEqual(blobName.optional, false); + + const methods = client.methods; + strictEqual(methods.length, 2); + const download = methods[0]; + strictEqual(download.name, "download"); + strictEqual(download.kind, "basic"); + strictEqual(download.parameters.length, 0); + + const downloadOp = download.operation; + strictEqual(downloadOp.parameters.length, 1); + strictEqual(downloadOp.parameters[0].name, "blob"); + strictEqual(downloadOp.parameters[0].correspondingMethodParams.length, 1); + strictEqual(downloadOp.parameters[0].correspondingMethodParams[0], blobName); + + const upload = methods[1]; + strictEqual(upload.name, "upload"); + strictEqual(upload.kind, "basic"); + strictEqual(upload.parameters.length, 0); + + const uploadOp = upload.operation; + strictEqual(uploadOp.parameters.length, 1); + strictEqual(uploadOp.parameters[0].name, "blobName"); + strictEqual(uploadOp.parameters[0].correspondingMethodParams.length, 1); + strictEqual(uploadOp.parameters[0].correspondingMethodParams[0], blobName); + }); + + it("storage example", async () => { + await runner.compileWithCustomization( + ` + @service + namespace Storage.Blob; + op download(@header("x-ms-version") version: string): void; + `, + ` + namespace MyCustomizations; + + model StorageBlobOptions { + version: string; + } + + @@clientInitialization(Storage.Blob, MyCustomizations.StorageBlobOptions); + `, + ); + const sdkPackage = runner.context.sdkPackage; + const model = sdkPackage.models.find((x) => x.name === "StorageBlobOptions"); + ok(model); + ok(model.usage & UsageFlags.ClientInitialization); + const version = model.properties.find(x => x.name === "version"); + ok(version); + + const client = sdkPackage.clients[0]; + strictEqual(client.initialization.model, model); + const method = client.methods[0]; + strictEqual(method.kind, "basic"); + strictEqual(method.name, "download"); + strictEqual(method.parameters.length, 0); + const op = method.operation; + strictEqual(op.parameters.length, 1); + const versionParam = op.parameters[0]; + strictEqual(versionParam.name, "version"); + strictEqual(versionParam.onClient, true); + strictEqual(versionParam.serializedName, "x-ms-version"); + strictEqual(versionParam.correspondingMethodParams[0], version) + }); +}); diff --git a/packages/typespec-client-generator-core/test/decorators/client-name.test.ts b/packages/typespec-client-generator-core/test/decorators/client-name.test.ts new file mode 100644 index 000000000..cf6274e1c --- /dev/null +++ b/packages/typespec-client-generator-core/test/decorators/client-name.test.ts @@ -0,0 +1,591 @@ +import { expectDiagnostics } from "@typespec/compiler/testing"; +import { strictEqual } from "assert"; +import { beforeEach, describe, it } from "vitest"; +import { SdkTestRunner, createSdkTestRunner } from "../test-host.js"; +import { getClientNameOverride } from "../../src/decorators.js"; +import { Model, Operation } from "@typespec/compiler"; + +describe("@clientName", () => { + let runner: SdkTestRunner; + + beforeEach(async () => { + runner = await createSdkTestRunner({ emitterName: "@azure-tools/typespec-python" }); + }); + + it("carry over", async () => { + const { Test1, Test2, func1, func2 } = (await runner.compile(` + @service({}) + @test namespace MyService { + @test + @clientName("Test1Rename") + model Test1{} + + @test + model Test2 is Test1{} + + @test + @route("/func1") + @clientName("func1Rename") + op func1(): void; + + @test + @route("/func2") + op func2 is func1; + } + `)) as { Test1: Model; Test2: Model; func1: Operation; func2: Operation }; + + strictEqual(getClientNameOverride(runner.context, Test1), "Test1Rename"); + strictEqual(getClientNameOverride(runner.context, Test2), undefined); + strictEqual(getClientNameOverride(runner.context, func1), "func1Rename"); + strictEqual(getClientNameOverride(runner.context, func2), undefined); + }); + + it("augment carry over", async () => { + const { Test1, Test2, func1, func2 } = (await runner.compileWithCustomization( + ` + @service({}) + @test namespace MyService { + @test + model Test1{} + + @test + model Test2 is Test1{} + + @test + @route("/func1") + op func1(): void; + + @test + @route("/func2") + op func2 is func1; + } + `, + ` + namespace Customizations; + + @@clientName(MyService.Test1, "Test1Rename"); + @@clientName(MyService.func1, "func1Rename"); + `, + )) as { Test1: Model; Test2: Model; func1: Operation; func2: Operation }; + + strictEqual(getClientNameOverride(runner.context, Test1), "Test1Rename"); + strictEqual(getClientNameOverride(runner.context, Test2), undefined); + strictEqual(getClientNameOverride(runner.context, func1), "func1Rename"); + strictEqual(getClientNameOverride(runner.context, func2), undefined); + }); + + it("@clientName with scope of versioning", async () => { + const testCode = ` + @service({ + title: "Contoso Widget Manager", + }) + @versioned(Contoso.WidgetManager.Versions) + namespace Contoso.WidgetManager; + + enum Versions { + v1, + v2, + } + + @clientName("TestJava", "java") + @clientName("TestCSharp", "csharp") + model Test {} + op test(@body body: Test): void; + `; + + // java + { + const runner = await createSdkTestRunner({ emitterName: "@azure-tools/typespec-java" }); + await runner.compile(testCode); + strictEqual(runner.context.sdkPackage.models[0].name, "TestJava"); + } + + // csharp + { + const runner = await createSdkTestRunner({ emitterName: "@azure-tools/typespec-csharp" }); + await runner.compile(testCode); + strictEqual(runner.context.sdkPackage.models[0].name, "TestCSharp"); + } + + // python + { + const runner = await createSdkTestRunner({ emitterName: "@azure-tools/typespec-python" }); + await runner.compile(testCode); + strictEqual(runner.context.sdkPackage.models[0].name, "Test"); + } + }); + + it("augmented @clientName with scope of versioning", async () => { + const testCode = ` + @service({ + title: "Contoso Widget Manager", + }) + @versioned(Contoso.WidgetManager.Versions) + namespace Contoso.WidgetManager; + + enum Versions { + v1, + v2, + } + + + model Test {} + op test(@body body: Test): void; + `; + + const customization = ` + namespace Customizations; + + @@clientName(Contoso.WidgetManager.Test, "TestCSharp", "csharp"); + @@clientName(Contoso.WidgetManager.Test, "TestJava", "java"); + `; + + // java + { + const runner = await createSdkTestRunner({ emitterName: "@azure-tools/typespec-java" }); + await runner.compileWithCustomization(testCode, customization); + strictEqual(runner.context.sdkPackage.models[0].name, "TestJava"); + } + + // csharp + { + const runner = await createSdkTestRunner({ emitterName: "@azure-tools/typespec-csharp" }); + await runner.compileWithCustomization(testCode, customization); + strictEqual(runner.context.sdkPackage.models[0].name, "TestCSharp"); + } + + // python + { + const runner = await createSdkTestRunner({ emitterName: "@azure-tools/typespec-python" }); + await runner.compileWithCustomization(testCode, customization); + strictEqual(runner.context.sdkPackage.models[0].name, "Test"); + } + }); + + it("decorator on template parameter", async function () { + await runner.compileAndDiagnose(` + @service({}) + namespace MyService; + + model ResourceBody { + @body + resource: Resource; + } + + @post + op do(...ResourceBody): void; + + @@clientName(ResourceBody.resource, "body"); + + model Test { + id: string; + prop: string; + } + + op test is do; + + `); + + strictEqual(runner.context.sdkPackage.clients[0].methods[0].parameters[0].name, "body"); + }); + + it("empty client name", async () => { + const diagnostics = await runner.diagnose(` + @service({}) + namespace MyService; + + @clientName(" ") + model Test { + id: string; + prop: string; + } + `); + + expectDiagnostics(diagnostics, { + code: "@azure-tools/typespec-client-generator-core/empty-client-name", + }); + }); + + it("duplicate model client name with a random language scope", async () => { + const diagnostics = await runner.diagnose( + ` + @service + namespace Contoso.WidgetManager; + + @clientName("Test", "random") + model Widget { + @key + id: int32; + } + + model Test { + prop1: string; + } + `, + ); + + expectDiagnostics(diagnostics, [ + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: 'Client name: "Test" is duplicated in language scope: "random"', + }, + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: + 'Client name: "Test" is defined somewhere causing nameing conflicts in language scope: "random"', + }, + ]); + }); + + it("duplicate model, enum, union client name with all language scopes", async () => { + const diagnostics = await runner.diagnose( + ` + @service + namespace Contoso.WidgetManager; + + @clientName("B") + enum A { + one + } + + model B {} + + @clientName("B") + union C {} + `, + ); + + expectDiagnostics(diagnostics, [ + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: + 'Client name: "B" is defined somewhere causing nameing conflicts in language scope: "AllScopes"', + }, + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: 'Client name: "B" is duplicated in language scope: "AllScopes"', + }, + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: 'Client name: "B" is duplicated in language scope: "AllScopes"', + }, + ]); + }); + + it("duplicate operation with all language scopes", async () => { + const diagnostics = await runner.diagnose( + ` + @service + namespace Contoso.WidgetManager; + + @clientName("b") + @route("/a") + op a(): void; + + @route("/b") + op b(): void; + `, + ); + + expectDiagnostics(diagnostics, [ + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: 'Client name: "b" is duplicated in language scope: "AllScopes"', + }, + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: + 'Client name: "b" is defined somewhere causing nameing conflicts in language scope: "AllScopes"', + }, + ]); + }); + + it("duplicate operation in interface with all language scopes", async () => { + const diagnostics = await runner.diagnose( + ` + @service + namespace Contoso.WidgetManager; + + interface C { + @clientName("b") + @route("/a") + op a(): void; + + @route("/b") + op b(): void; + } + `, + ); + + expectDiagnostics(diagnostics, [ + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: 'Client name: "b" is duplicated in language scope: "AllScopes"', + }, + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: + 'Client name: "b" is defined somewhere causing nameing conflicts in language scope: "AllScopes"', + }, + ]); + }); + + it("duplicate scalar with all language scopes", async () => { + const diagnostics = await runner.diagnose( + ` + @service + namespace Contoso.WidgetManager; + + @clientName("b") + scalar a extends string; + + scalar b extends string; + `, + ); + + expectDiagnostics(diagnostics, [ + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: 'Client name: "b" is duplicated in language scope: "AllScopes"', + }, + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: + 'Client name: "b" is defined somewhere causing nameing conflicts in language scope: "AllScopes"', + }, + ]); + }); + + it("duplicate interface with all language scopes", async () => { + const diagnostics = await runner.diagnose( + ` + @service + namespace Contoso.WidgetManager; + + @clientName("B") + @route("/a") + interface A { + } + + @route("/b") + interface B { + } + `, + ); + + expectDiagnostics(diagnostics, [ + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: 'Client name: "B" is duplicated in language scope: "AllScopes"', + }, + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: + 'Client name: "B" is defined somewhere causing nameing conflicts in language scope: "AllScopes"', + }, + ]); + }); + + it("duplicate model property with all language scopes", async () => { + const diagnostics = await runner.diagnose( + ` + @service + namespace Contoso.WidgetManager; + + model A { + @clientName("prop2") + prop1: string; + prop2: string; + } + `, + ); + + expectDiagnostics(diagnostics, [ + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: 'Client name: "prop2" is duplicated in language scope: "AllScopes"', + }, + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: + 'Client name: "prop2" is defined somewhere causing nameing conflicts in language scope: "AllScopes"', + }, + ]); + }); + + it("duplicate enum member with all language scopes", async () => { + const diagnostics = await runner.diagnose( + ` + @service + namespace Contoso.WidgetManager; + + enum A { + @clientName("two") + one, + two + } + `, + ); + + expectDiagnostics(diagnostics, [ + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: 'Client name: "two" is duplicated in language scope: "AllScopes"', + }, + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: + 'Client name: "two" is defined somewhere causing nameing conflicts in language scope: "AllScopes"', + }, + ]); + }); + + it("duplicate union variant with all language scopes", async () => { + const diagnostics = await runner.diagnose( + ` + @service + namespace Contoso.WidgetManager; + + union Foo { + @clientName("b") + a: {}, + b: {} + } + `, + ); + + expectDiagnostics(diagnostics, [ + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: 'Client name: "b" is duplicated in language scope: "AllScopes"', + }, + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: + 'Client name: "b" is defined somewhere causing nameing conflicts in language scope: "AllScopes"', + }, + ]); + }); + + it("duplicate namespace with all language scopes", async () => { + const diagnostics = await runner.diagnose( + ` + @service + namespace A{ + namespace B {} + @clientName("B") + namespace C {} + } + `, + ); + + expectDiagnostics(diagnostics, [ + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: + 'Client name: "B" is defined somewhere causing nameing conflicts in language scope: "AllScopes"', + }, + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: 'Client name: "B" is duplicated in language scope: "AllScopes"', + }, + ]); + }); + + it("duplicate enum and model within nested namespace for all language scopes", async () => { + const diagnostics = await runner.diagnose( + ` + @service + namespace A{ + namespace B { + @clientName("B") + enum A { + one + } + + model B {} + } + + @clientName("B") + model A {} + } + `, + ); + + expectDiagnostics(diagnostics, [ + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: + 'Client name: "B" is defined somewhere causing nameing conflicts in language scope: "AllScopes"', + }, + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: 'Client name: "B" is duplicated in language scope: "AllScopes"', + }, + ]); + }); + + it("duplicate model with model only generation for all language scopes", async () => { + const diagnostics = await runner.diagnose( + ` + model Foo {} + + @clientName("Foo") + model Bar {} + `, + ); + + expectDiagnostics(diagnostics, [ + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: + 'Client name: "Foo" is defined somewhere causing nameing conflicts in language scope: "AllScopes"', + }, + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: 'Client name: "Foo" is duplicated in language scope: "AllScopes"', + }, + ]); + }); + + it("duplicate model client name with multiple language scopes", async () => { + const diagnostics = await runner.diagnose( + ` + @service + namespace Contoso.WidgetManager; + + @clientName("Test", "csharp,python,java") + model Widget { + @key + id: int32; + } + + @clientName("Widget", "java") + model Test { + prop1: string; + } + `, + ); + + expectDiagnostics(diagnostics, [ + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: 'Client name: "Test" is duplicated in language scope: "csharp"', + }, + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: + 'Client name: "Test" is defined somewhere causing nameing conflicts in language scope: "csharp"', + }, + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: 'Client name: "Test" is duplicated in language scope: "python"', + }, + { + code: "@azure-tools/typespec-client-generator-core/duplicate-client-name", + message: + 'Client name: "Test" is defined somewhere causing nameing conflicts in language scope: "python"', + }, + ]); + }); +}); From af4228684881f10aee9933f2fc7a1e5950553805 Mon Sep 17 00:00:00 2001 From: iscai-msft Date: Tue, 22 Oct 2024 13:27:17 -0400 Subject: [PATCH 11/11] format --- .../test/decorators/client-initialization.test.ts | 4 ++-- .../test/decorators/client-name.test.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/typespec-client-generator-core/test/decorators/client-initialization.test.ts b/packages/typespec-client-generator-core/test/decorators/client-initialization.test.ts index 2a1daf23f..fa3455a45 100644 --- a/packages/typespec-client-generator-core/test/decorators/client-initialization.test.ts +++ b/packages/typespec-client-generator-core/test/decorators/client-initialization.test.ts @@ -549,7 +549,7 @@ describe("@clientInitialization", () => { const model = sdkPackage.models.find((x) => x.name === "StorageBlobOptions"); ok(model); ok(model.usage & UsageFlags.ClientInitialization); - const version = model.properties.find(x => x.name === "version"); + const version = model.properties.find((x) => x.name === "version"); ok(version); const client = sdkPackage.clients[0]; @@ -564,6 +564,6 @@ describe("@clientInitialization", () => { strictEqual(versionParam.name, "version"); strictEqual(versionParam.onClient, true); strictEqual(versionParam.serializedName, "x-ms-version"); - strictEqual(versionParam.correspondingMethodParams[0], version) + strictEqual(versionParam.correspondingMethodParams[0], version); }); }); diff --git a/packages/typespec-client-generator-core/test/decorators/client-name.test.ts b/packages/typespec-client-generator-core/test/decorators/client-name.test.ts index cf6274e1c..c2ec11811 100644 --- a/packages/typespec-client-generator-core/test/decorators/client-name.test.ts +++ b/packages/typespec-client-generator-core/test/decorators/client-name.test.ts @@ -1,9 +1,9 @@ +import { Model, Operation } from "@typespec/compiler"; import { expectDiagnostics } from "@typespec/compiler/testing"; import { strictEqual } from "assert"; import { beforeEach, describe, it } from "vitest"; -import { SdkTestRunner, createSdkTestRunner } from "../test-host.js"; import { getClientNameOverride } from "../../src/decorators.js"; -import { Model, Operation } from "@typespec/compiler"; +import { SdkTestRunner, createSdkTestRunner } from "../test-host.js"; describe("@clientName", () => { let runner: SdkTestRunner;