-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[tcgc] add client initialization usage #1664
base: main
Are you sure you want to change the base?
Changes from 8 commits
ca4f0d8
24dca2d
b267cdf
6836ecb
b9bf536
9bb8823
76b058d
72c9159
f9a7f63
fbf5668
ad69320
af42286
18e7212
96782b3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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,10 +69,12 @@ import { | |
SdkEnumType, | ||
SdkEnumValueType, | ||
SdkInitializationType, | ||
SdkMethodParameter, | ||
SdkModelPropertyType, | ||
SdkModelPropertyTypeBase, | ||
SdkModelType, | ||
SdkOperationGroup, | ||
SdkParameter, | ||
SdkTupleType, | ||
SdkType, | ||
SdkUnionType, | ||
|
@@ -685,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, | ||
|
@@ -781,6 +773,75 @@ 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 { | ||
access: client.kind === "SdkClient" ? "public" : "internal", | ||
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: [], | ||
}, | ||
}; | ||
} | ||
|
||
export function getSdkInitializationType( | ||
context: TCGCContext, | ||
client: SdkClient | SdkOperationGroup, | ||
model: Model, | ||
): SdkInitializationType { | ||
// convert to SDK type | ||
const existingModel = context.modelsMap?.get(model) as SdkModelType<SdkParameter> | undefined; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we allow to reuse model in operation as a client initialization model? if so, can we have a test? if not, we could return directly and shall have some lint. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @m-nash since c# appears to be the main sdk using client initialization model generation, is there anything precluding us from having a model be used in both scenarios? |
||
let sdkModel: SdkModelType<SdkParameter>; | ||
if (existingModel) { | ||
sdkModel = existingModel; | ||
} else { | ||
sdkModel = getSdkModel(context, model) as SdkModelType<SdkParameter>; | ||
|
||
sdkModel.properties = sdkModel.properties.map( | ||
(property: SdkModelPropertyType): SdkMethodParameter => { | ||
property.onClient = true; | ||
property.kind = "method"; | ||
return property as SdkMethodParameter; | ||
}, | ||
); | ||
} | ||
const initializationModel: SdkInitializationType = { | ||
access: client.kind === "SdkClient" ? "public" : "internal", | ||
model: sdkModel, | ||
}; | ||
let clientParams = context.__clientToParameters.get(client.type); | ||
if (!clientParams) { | ||
clientParams = []; | ||
context.__clientToParameters.set(client.type, clientParams); | ||
} | ||
|
||
for (const prop of initializationModel.model.properties) { | ||
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, { | ||
propagation: false, | ||
}); | ||
updateModelsMap(context, model, sdkModel); | ||
return initializationModel; | ||
} | ||
|
||
function getUnionAsEnumValueType( | ||
context: TCGCContext, | ||
union: Union, | ||
|
@@ -1778,6 +1839,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); | ||
} | ||
iscai-msft marked this conversation as resolved.
Show resolved
Hide resolved
|
||
while (ogs.length) { | ||
const operationGroup = ogs.pop(); | ||
for (const operation of listOperationsInOperationGroup(context, operationGroup!)) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i've realized we can't modify the
.access
on our existingSdkInitializationType
to denote whether a client is publicly or internally initialized. There is both the context that the client options model is used, and the client options model itself. In this case, the context that the client options model is used hasaccess
that depends on whether it's a client or og. However, that doesn't change the actualaccess
of the client options model itself.This is a breaking change, so want to call this out and will call it out more in our sync