зеркало из https://github.com/Azure/autorest.git
Inlcude csharp rename decorator when openai-to-typespec generating tsp (#4907)
Fixes https://github.com/Azure/autorest.csharp/issues/4236. Generate csharp renaming decorator when openai-to-typespec generating tsp. (include rename of resource, resource.property, model, model.property, enum, enum.member and operation name) related autorest.csharp change can be found at https://github.com/Azure/autorest.csharp/pull/4380
This commit is contained in:
Родитель
cc5a4dc000
Коммит
63ffe68961
|
@ -296,3 +296,4 @@ regression-tests/output
|
|||
|
||||
# TS incremental build cache
|
||||
*.tsbuildinfo
|
||||
*.njsproj
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "@autorest/openapi-to-typespec",
|
||||
"comment": "support generating csharp rename decorator when converting to tsp",
|
||||
"type": "minor"
|
||||
}
|
||||
],
|
||||
"packageName": "@autorest/openapi-to-typespec"
|
||||
}
|
|
@ -10,20 +10,18 @@
|
|||
#>
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]
|
||||
# Specifies the swagger config file, not the swagger json, but the readme config.
|
||||
[Parameter(Mandatory = $true, HelpMessage = "Specifies the swagger config file (not the swagger json, but the readme config) or autorest.md file in the azure-sdk-for-net repo if .net related configuration is expected to be included.")]
|
||||
[string]
|
||||
$swaggerConfigFile,
|
||||
[Parameter(Mandatory = $false, HelpMessage = "Specified the output folder, deafult to current folder.")]
|
||||
[string]
|
||||
# Specified the output folder, deafult to current folder.
|
||||
$outputFolder,
|
||||
[Parameter(Mandatory = $false, HelpMessage = "Specified the csharp codegen, default to https://aka.ms/azsdk/openapi-to-typespec-csharp.")]
|
||||
[string]
|
||||
# Specified the csharp codegen, default to https://aka.ms/azsdk/openapi-to-typespec-csharp.
|
||||
$csharpCodegen = "https://aka.ms/azsdk/openapi-to-typespec-csharp",
|
||||
[Parameter(Mandatory = $false, HelpMessage = "Specified the converter codegen, default to https://aka.ms/azsdk/openapi-to-typespec.")]
|
||||
[string]
|
||||
# Specified the converter codegen, default to https://aka.ms/azsdk/openapi-to-typespec.
|
||||
$converterCodegen = "."
|
||||
)
|
||||
$converterCodegen = ".")
|
||||
|
||||
function GenerateMetadata ()
|
||||
{
|
||||
|
@ -42,7 +40,7 @@ function GenerateMetadata ()
|
|||
function DoConvert ()
|
||||
{
|
||||
Write-Host "##Converting from swagger to tsp with in $outputFolder with $converterCodegen"
|
||||
$cmd = "autorest --version=3.10.1 --openapi-to-typespec --isAzureSpec --isArm --use=`"$converterCodegen`" --output-folder=$outputFolder $swaggerConfigFile"
|
||||
$cmd = "autorest --version=3.10.1 --openapi-to-typespec --csharp=false --isAzureSpec --isArm --use=`"$converterCodegen`" --output-folder=$outputFolder $swaggerConfigFile"
|
||||
Write-Host "$cmd"
|
||||
Invoke-Expression $cmd
|
||||
if ($LASTEXITCODE) { exit $LASTEXITCODE }
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
import { getSession } from "../autorest-session";
|
||||
import { generateArmResourceClientDecorator, generateObjectClientDecorator } from "../generate/generate-client";
|
||||
import {
|
||||
generateArmResourceClientDecorator,
|
||||
generateEnumClientDecorator,
|
||||
generateObjectClientDecorator,
|
||||
} from "../generate/generate-client";
|
||||
import { TypespecProgram } from "../interfaces";
|
||||
import { getOptions } from "../options";
|
||||
import { formatTypespecFile } from "../utils/format";
|
||||
|
@ -34,8 +38,14 @@ function generateClient(program: TypespecProgram) {
|
|||
.filter((r) => r !== "")
|
||||
.join("\n\n")
|
||||
: "";
|
||||
if (objects === "" && armResources === "") {
|
||||
|
||||
const enums = models.enums
|
||||
.map(generateEnumClientDecorator)
|
||||
.filter((r) => r !== "")
|
||||
.join("\n\n");
|
||||
|
||||
if (objects === "" && armResources === "" && enums === "") {
|
||||
return "";
|
||||
}
|
||||
return [imports, "\n", namespaces, "\n", objects, "\n", armResources].join("\n");
|
||||
return [imports, "\n", namespaces, "\n", objects, "\n", armResources, "\n", enums].join("\n");
|
||||
}
|
||||
|
|
|
@ -51,8 +51,8 @@ function getArmResourceImports(program: TypespecProgram): string[] {
|
|||
const resourceMetadata = getArmResourcesMetadata();
|
||||
const imports: string[] = [];
|
||||
|
||||
for (const resource in resourceMetadata) {
|
||||
imports.push(`import "./${resourceMetadata[resource].SwaggerModelName}.tsp";`);
|
||||
for (const resource in resourceMetadata.Resources) {
|
||||
imports.push(`import "./${resourceMetadata.Resources[resource].SwaggerModelName}.tsp";`);
|
||||
}
|
||||
|
||||
if (program.operationGroups.length > 0) {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import pluralize from "pluralize";
|
||||
import { TspArmResource, TypespecObject } from "../interfaces";
|
||||
import { TspArmResource, TypespecObject, TypespecEnum, TypespecOperation } from "../interfaces";
|
||||
import { generateAugmentedDecorators } from "../utils/decorators";
|
||||
|
||||
export function generateObjectClientDecorator(typespecObject: TypespecObject) {
|
||||
const definitions: string[] = [];
|
||||
|
||||
definitions.push(generateAugmentedDecorators(typespecObject.name, typespecObject.clientDecorators));
|
||||
|
||||
for (const property of typespecObject.properties) {
|
||||
const decorators = generateAugmentedDecorators(
|
||||
`${typespecObject.name}.${property.name}`,
|
||||
|
@ -16,11 +18,50 @@ export function generateObjectClientDecorator(typespecObject: TypespecObject) {
|
|||
return definitions.join("\n");
|
||||
}
|
||||
|
||||
export function generateEnumClientDecorator(typespecEnum: TypespecEnum) {
|
||||
const definitions: string[] = [];
|
||||
|
||||
definitions.push(generateAugmentedDecorators(typespecEnum.name, typespecEnum.clientDecorators));
|
||||
|
||||
for (const choice of typespecEnum.members) {
|
||||
const decorators = generateAugmentedDecorators(`${typespecEnum.name}.${choice.name}`, choice.clientDecorators);
|
||||
decorators && definitions.push(decorators);
|
||||
}
|
||||
|
||||
return definitions.join("\n");
|
||||
}
|
||||
|
||||
export function generateOperationClientDecorator(operation: TypespecOperation) {
|
||||
const definitions: string[] = [];
|
||||
|
||||
definitions.push(generateAugmentedDecorators(operation.name, operation.clientDecorators));
|
||||
|
||||
return definitions.join("\n");
|
||||
}
|
||||
|
||||
export function generateArmResourceClientDecorator(resource: TspArmResource): string {
|
||||
const definitions: string[] = [];
|
||||
|
||||
const formalOperationGroupName = pluralize(resource.name);
|
||||
let targetName = formalOperationGroupName;
|
||||
|
||||
if (resource.name === formalOperationGroupName) {
|
||||
return `@@clientName(${formalOperationGroupName}OperationGroup, "${formalOperationGroupName}")`;
|
||||
targetName = `${formalOperationGroupName}OperationGroup}`;
|
||||
definitions.push(`@@clientName(${formalOperationGroupName}OperationGroup, "${formalOperationGroupName}")`);
|
||||
}
|
||||
return "";
|
||||
|
||||
if (resource.clientDecorators && resource.clientDecorators.length > 0)
|
||||
definitions.push(generateAugmentedDecorators(resource.name, resource.clientDecorators));
|
||||
|
||||
for (const op of resource.resourceOperations) {
|
||||
if (op.clientDecorators && op.clientDecorators.length > 0)
|
||||
definitions.push(generateAugmentedDecorators(`${targetName}.${op.name}`, op.clientDecorators));
|
||||
}
|
||||
|
||||
for (const property of resource.properties) {
|
||||
const decorators = generateAugmentedDecorators(`${targetName}.${property.name}`, property.clientDecorators);
|
||||
decorators && definitions.push(decorators);
|
||||
}
|
||||
|
||||
return definitions.join("\n");
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ export interface TypespecOptions {
|
|||
export interface TypespecChoiceValue extends WithDoc {
|
||||
name: string;
|
||||
value: string | number | boolean;
|
||||
clientDecorators?: TypespecDecorator[];
|
||||
}
|
||||
|
||||
export interface WithDoc {
|
||||
|
@ -42,6 +43,7 @@ export interface TypespecOperation extends WithDoc, WithSummary, WithFixMe {
|
|||
operationGroupName?: string;
|
||||
operationId?: string;
|
||||
examples?: Record<string, Record<string, unknown>>;
|
||||
clientDecorators?: TypespecDecorator[];
|
||||
}
|
||||
|
||||
export type ResourceKind =
|
||||
|
@ -120,6 +122,7 @@ export interface TypespecEnum extends TypespecDataType {
|
|||
members: TypespecChoiceValue[];
|
||||
isExtensible: boolean;
|
||||
decorators?: TypespecDecorator[];
|
||||
clientDecorators?: TypespecDecorator[];
|
||||
}
|
||||
|
||||
export interface WithFixMe {
|
||||
|
@ -137,6 +140,7 @@ export interface TypespecParameter extends TypespecDataType {
|
|||
isOptional: boolean;
|
||||
type: string;
|
||||
decorators?: TypespecDecorator[];
|
||||
clientDecorators?: TypespecDecorator[];
|
||||
location: TypespecParameterLocation;
|
||||
serializedName: string;
|
||||
defaultValue?: any;
|
||||
|
@ -171,6 +175,7 @@ export interface TypespecObject extends TypespecDataType {
|
|||
extendedParents?: string[];
|
||||
spreadParents?: string[];
|
||||
decorators?: TypespecDecorator[];
|
||||
clientDecorators?: TypespecDecorator[];
|
||||
alias?: TypespecAlias;
|
||||
}
|
||||
|
||||
|
@ -201,6 +206,7 @@ export interface TspArmResourceOperationBase extends WithDoc, WithFixMe {
|
|||
name: string;
|
||||
templateParameters?: string[];
|
||||
decorators?: TypespecDecorator[];
|
||||
clientDecorators?: TypespecDecorator[];
|
||||
operationId?: string;
|
||||
examples?: Record<string, Record<string, unknown>>;
|
||||
customizations?: string[];
|
||||
|
|
|
@ -17,6 +17,7 @@ import { emitTypespecConfig } from "./emiters/emit-typespec-config";
|
|||
import { getModel } from "./model";
|
||||
import { pretransformArmResources } from "./pretransforms/arm-pretransform";
|
||||
import { pretransformNames } from "./pretransforms/name-pretransform";
|
||||
import { pretransformRename } from "./pretransforms/rename-pretransform";
|
||||
import { markErrorModels } from "./utils/errors";
|
||||
import { markPagination } from "./utils/paging";
|
||||
import { markResources } from "./utils/resources";
|
||||
|
@ -27,6 +28,7 @@ export async function processConverter(host: AutorestExtensionHost) {
|
|||
const codeModel = session.model;
|
||||
pretransformNames(codeModel);
|
||||
pretransformArmResources(codeModel);
|
||||
pretransformRename(codeModel);
|
||||
markPagination(codeModel);
|
||||
markErrorModels(codeModel);
|
||||
markResources(codeModel);
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
import {
|
||||
ChoiceSchema,
|
||||
CodeModel,
|
||||
ObjectSchema,
|
||||
SealedChoiceSchema,
|
||||
Schema,
|
||||
ChoiceValue,
|
||||
Property,
|
||||
Parameter,
|
||||
SchemaType,
|
||||
Operation,
|
||||
} from "@autorest/codemodel";
|
||||
import { TypespecDecorator } from "../interfaces";
|
||||
import { getOptions } from "../options";
|
||||
import { getLogger } from "../utils/logger";
|
||||
import { Metadata, getArmResourcesMetadata } from "../utils/resource-discovery";
|
||||
|
||||
type RenamableSchema = Schema | Property | Parameter | ChoiceValue | Operation;
|
||||
|
||||
const logger = () => getLogger("rename-pretransform");
|
||||
|
||||
export function pretransformRename(codeModel: CodeModel): void {
|
||||
const { isArm } = getOptions();
|
||||
if (!isArm) {
|
||||
return;
|
||||
}
|
||||
|
||||
const metadata = getArmResourcesMetadata();
|
||||
|
||||
applyRenameMapping(metadata, codeModel);
|
||||
applyOverrideOperationName(metadata, codeModel);
|
||||
}
|
||||
|
||||
export function createCSharpNameDecorator(schema: RenamableSchema): TypespecDecorator {
|
||||
return {
|
||||
name: "clientName",
|
||||
module: "@azure-tools/typespec-client-generator-core",
|
||||
namespace: "Azure.ClientGenerator.Core",
|
||||
arguments: [schema.language.csharp!.name, "csharp"],
|
||||
};
|
||||
}
|
||||
|
||||
function parseNewCSharpNameAndSetToSchema(schema: RenamableSchema, renameValue: string) {
|
||||
const newName = parseNewName(renameValue);
|
||||
setSchemaCSharpName(schema, newName);
|
||||
}
|
||||
|
||||
function setSchemaCSharpName(schema: RenamableSchema, newName: string) {
|
||||
if (!schema.language.csharp)
|
||||
schema.language.csharp = { name: newName, description: schema.language.default.description };
|
||||
else schema.language.csharp.name = newName;
|
||||
}
|
||||
|
||||
function parseNewName(value: string) {
|
||||
// TODO: format not supported
|
||||
return value.split("|")[0].trim();
|
||||
}
|
||||
|
||||
function applyOverrideOperationName(metadata: Metadata, codeModel: CodeModel) {
|
||||
for (const opId in metadata.OverrideOperationName) {
|
||||
const found = codeModel.operationGroups.flatMap((og) => og.operations).find((op) => op.operationId === opId);
|
||||
if (found) parseNewCSharpNameAndSetToSchema(found, metadata.OverrideOperationName[opId]);
|
||||
else
|
||||
logger().warning(
|
||||
`Can't find operation to rename for OverrideOperationName rule: ${opId}->${metadata.OverrideOperationName[opId]}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function applyRenameMapping(metadata: Metadata, codeModel: CodeModel) {
|
||||
for (const key in metadata.RenameMapping) {
|
||||
const subKeys = key
|
||||
.split(".")
|
||||
.map((s) => s.trim())
|
||||
.filter((s) => s.length > 0);
|
||||
if (subKeys.length === 0) continue;
|
||||
const lowerFirstSubKey = subKeys[0].toLowerCase();
|
||||
const value = metadata.RenameMapping[key];
|
||||
|
||||
const found: Schema | undefined = [
|
||||
...(codeModel.schemas.choices ?? []),
|
||||
...(codeModel.schemas.sealedChoices ?? []),
|
||||
...(codeModel.schemas.objects ?? []),
|
||||
].find((o: Schema) => o.language.default.name.toLowerCase() === lowerFirstSubKey);
|
||||
|
||||
if (!found) {
|
||||
logger().warning(`Can't find object or enum for RenameMapping rule: ${key} -> ${value}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (found.type === SchemaType.Choice || found.type == SchemaType.SealedChoice) {
|
||||
transformEnum(subKeys, value, found as ChoiceSchema | SealedChoiceSchema);
|
||||
} else if (found.type === SchemaType.Object) {
|
||||
transformObject(subKeys, value, found as ObjectSchema);
|
||||
} else {
|
||||
logger().error(`Unexpected schema type '${found.type}' found with key ${key}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function transformEnum(keys: string[], value: string, target: ChoiceSchema | SealedChoiceSchema) {
|
||||
if (keys.length === 1) parseNewCSharpNameAndSetToSchema(target, value);
|
||||
else if (keys.length === 2) {
|
||||
const lowerMemberValue = keys[1].toLowerCase();
|
||||
const found = target.choices.find((c) => c.language.default.name.toLowerCase() === lowerMemberValue);
|
||||
if (found) parseNewCSharpNameAndSetToSchema(found, value);
|
||||
else logger().warning(`Can't find enum member for RenameMapping rule: ${keys.join(".")} -> ${value}`);
|
||||
} else {
|
||||
logger().error(`Unexpected keys for enum RenameMapping: ${keys.join(".")}`);
|
||||
}
|
||||
}
|
||||
|
||||
function transformObject(keys: string[], value: string, target: ObjectSchema) {
|
||||
if (keys.length === 1) parseNewCSharpNameAndSetToSchema(target, value);
|
||||
else if (keys.length === 2) {
|
||||
const lowerPropertyName = keys[1].toLowerCase();
|
||||
const found = target.properties?.find((p) => p.language.default.name.toLowerCase() === lowerPropertyName);
|
||||
if (found) parseNewCSharpNameAndSetToSchema(found, value);
|
||||
else logger().warning(`Can't find object property for RenameMapping rule: ${keys.join(".")} -> ${value}`);
|
||||
} else if (keys.length > 2) {
|
||||
// handle flatten scenario
|
||||
const lowerPropName = keys.pop()?.toLowerCase();
|
||||
let cur = target;
|
||||
for (let i = 1; i < keys.length && cur; i++) {
|
||||
const foundProp = cur.properties?.find((p) => p.language.default.name.toLowerCase() === keys[i].toLowerCase());
|
||||
cur = foundProp?.schema as ObjectSchema;
|
||||
}
|
||||
const foundProp = cur?.properties?.find((p) => p.language.default.name.toLowerCase() === lowerPropName);
|
||||
if (foundProp) parseNewCSharpNameAndSetToSchema(foundProp, value);
|
||||
else {
|
||||
logger().warning(`Can't find object property for RenameMapping rule: ${keys.join(".")} -> ${value}`);
|
||||
}
|
||||
} else {
|
||||
logger().error(`Unexpected keys for object property RenameMapping: ${keys.join(".")}`);
|
||||
}
|
||||
}
|
|
@ -14,6 +14,8 @@ import {
|
|||
isFirstLevelResource,
|
||||
} from "../interfaces";
|
||||
import { getOptions, updateOptions } from "../options";
|
||||
import { createCSharpNameDecorator } from "../pretransforms/rename-pretransform";
|
||||
import { getOperationClientDecorators } from "../utils/decorators";
|
||||
import {
|
||||
ArmResource,
|
||||
ArmResourceSchema,
|
||||
|
@ -105,6 +107,11 @@ export function transformTspArmResource(schema: ArmResourceSchema): TspArmResour
|
|||
decorators.push({ name: "extensionResource" });
|
||||
}
|
||||
|
||||
const armResourceOperations = operations[0];
|
||||
const otherOperations = operations[1];
|
||||
|
||||
const clientDecorators = buildResourceClientDecorators(schema, armResourceOperations, otherOperations);
|
||||
|
||||
return {
|
||||
fixMe,
|
||||
resourceKind: getResourceKind(schema),
|
||||
|
@ -119,8 +126,9 @@ export function transformTspArmResource(schema: ArmResourceSchema): TspArmResour
|
|||
propertiesPropertyDescription,
|
||||
doc: schema.language.default.description,
|
||||
decorators,
|
||||
resourceOperations: operations[0],
|
||||
normalOperations: operations[1],
|
||||
clientDecorators,
|
||||
resourceOperations: armResourceOperations,
|
||||
normalOperations: otherOperations,
|
||||
optionalStandardProperties: getArmCommonTypeVersion() ? getResourceOptionalStandardProperties(schema) : [],
|
||||
baseModelName,
|
||||
locationParent: getLocationParent(schema),
|
||||
|
@ -190,6 +198,7 @@ function convertResourceReadOperation(
|
|||
kind: "ArmResourceRead",
|
||||
name: getOperationName(operation.OperationID),
|
||||
operationId: operation.OperationID,
|
||||
clientDecorators: getOperationClientDecorators(swaggerOperation),
|
||||
templateParameters: baseParameters
|
||||
? [resourceMetadata.SwaggerModelName, baseParameters]
|
||||
: [resourceMetadata.SwaggerModelName],
|
||||
|
@ -206,6 +215,7 @@ function convertResourceExistsOperation(resourceMetadata: ArmResource): TspArmRe
|
|||
doc: swaggerOperation.language.default.description,
|
||||
kind: "ArmResourceExists",
|
||||
name: swaggerOperation.operationId ? getOperationName(swaggerOperation.operationId) : "exists",
|
||||
clientDecorators: getOperationClientDecorators(swaggerOperation),
|
||||
operationId: swaggerOperation.operationId,
|
||||
parameters: [
|
||||
`...ResourceInstanceParameters<${resourceMetadata.SwaggerModelName}, BaseParameters<${resourceMetadata.SwaggerModelName}>>`,
|
||||
|
@ -256,6 +266,7 @@ function convertResourceCreateOrReplaceOperation(
|
|||
doc: operation.Description,
|
||||
kind: isLongRunning ? "ArmResourceCreateOrReplaceAsync" : "ArmResourceCreateOrReplaceSync",
|
||||
name: operationName,
|
||||
clientDecorators: getOperationClientDecorators(swaggerOperation),
|
||||
operationId: operation.OperationID,
|
||||
templateParameters: templateParameters,
|
||||
examples: swaggerOperation.extensions?.["x-ms-examples"],
|
||||
|
@ -343,6 +354,7 @@ function convertResourceUpdateOperation(
|
|||
doc: operation.Description,
|
||||
kind: kind as any,
|
||||
name: getOperationName(operation.OperationID),
|
||||
clientDecorators: getOperationClientDecorators(swaggerOperation),
|
||||
operationId: operation.OperationID,
|
||||
templateParameters,
|
||||
examples: swaggerOperation.extensions?.["x-ms-examples"],
|
||||
|
@ -379,6 +391,7 @@ function convertResourceDeleteOperation(
|
|||
: "ArmResourceDeleteWithoutOkAsync"
|
||||
: "ArmResourceDeleteSync",
|
||||
name: getOperationName(operation.OperationID),
|
||||
clientDecorators: getOperationClientDecorators(swaggerOperation),
|
||||
operationId: operation.OperationID,
|
||||
templateParameters,
|
||||
examples: swaggerOperation.extensions?.["x-ms-examples"],
|
||||
|
@ -415,6 +428,7 @@ function convertResourceListOperations(
|
|||
doc: operation.Description,
|
||||
kind: "ArmResourceListByParent",
|
||||
name: getOperationName(operation.OperationID),
|
||||
clientDecorators: getOperationClientDecorators(swaggerOperation),
|
||||
operationId: operation.OperationID,
|
||||
templateParameters: templateParameters,
|
||||
examples: swaggerOperation.extensions?.["x-ms-examples"],
|
||||
|
@ -448,6 +462,7 @@ function convertResourceListOperations(
|
|||
doc: operation.Description,
|
||||
kind: "ArmResourceListAtScope",
|
||||
name: getOperationName(operation.OperationID),
|
||||
clientDecorators: getOperationClientDecorators(swaggerOperation),
|
||||
operationId: operation.OperationID,
|
||||
templateParameters,
|
||||
examples: swaggerOperation.extensions?.["x-ms-examples"],
|
||||
|
@ -457,6 +472,7 @@ function convertResourceListOperations(
|
|||
doc: operation.Description,
|
||||
kind: "ArmListBySubscription",
|
||||
name: getOperationName(operation.OperationID),
|
||||
clientDecorators: getOperationClientDecorators(swaggerOperation),
|
||||
operationId: operation.OperationID,
|
||||
templateParameters: [resourceMetadata.SwaggerModelName],
|
||||
examples: swaggerOperation.extensions?.["x-ms-examples"],
|
||||
|
@ -483,6 +499,7 @@ function convertResourceListOperations(
|
|||
name: swaggerOperation.operationId
|
||||
? getOperationName(swaggerOperation.operationId)
|
||||
: `listBy${resourceMetadata.Parents[0].replace(/Resource$/, "")}`,
|
||||
clientDecorators: getOperationClientDecorators(swaggerOperation),
|
||||
operationId: swaggerOperation.operationId,
|
||||
templateParameters: baseParameters
|
||||
? [resourceMetadata.SwaggerModelName, baseParameters]
|
||||
|
@ -549,6 +566,7 @@ function convertResourceActionOperations(
|
|||
doc: operation.Description,
|
||||
kind: kind as any,
|
||||
name: operationName,
|
||||
clientDecorators: getOperationClientDecorators(swaggerOperation),
|
||||
operationId: operation.OperationID,
|
||||
templateParameters,
|
||||
examples: swaggerOperation.extensions?.["x-ms-examples"],
|
||||
|
@ -585,6 +603,7 @@ function convertCheckNameAvailabilityOperations(
|
|||
doc: operation.Description,
|
||||
kind: "checkLocalNameAvailability",
|
||||
name: getOperationName(operation.OperationID),
|
||||
clientDecorators: getOperationClientDecorators(swaggerOperation),
|
||||
operationId: operation.OperationID,
|
||||
examples: swaggerOperation.extensions?.["x-ms-examples"],
|
||||
templateParameters: [request, response],
|
||||
|
@ -594,6 +613,7 @@ function convertCheckNameAvailabilityOperations(
|
|||
doc: operation.Description,
|
||||
kind: "checkGlobalNameAvailability",
|
||||
name: getOperationName(operation.OperationID),
|
||||
clientDecorators: getOperationClientDecorators(swaggerOperation),
|
||||
operationId: operation.OperationID,
|
||||
examples: swaggerOperation.extensions?.["x-ms-examples"],
|
||||
templateParameters: [request, response],
|
||||
|
@ -860,6 +880,19 @@ function buildResourceDecorators(schema: ArmResourceSchema): TypespecDecorator[]
|
|||
return resourceModelDecorators;
|
||||
}
|
||||
|
||||
function buildResourceClientDecorators(
|
||||
schema: ArmResourceSchema,
|
||||
armResourceOperations: TspArmResourceOperation[],
|
||||
normalOperations: TypespecOperation[],
|
||||
): TypespecDecorator[] {
|
||||
const clientDecorator: TypespecDecorator[] = [];
|
||||
if (schema.language.csharp?.name) {
|
||||
clientDecorator.push(createCSharpNameDecorator(schema));
|
||||
}
|
||||
|
||||
return clientDecorator;
|
||||
}
|
||||
|
||||
function getSingletonName(schema: ArmResourceSchema): string {
|
||||
const key = schema.resourceMetadata.ResourceKey;
|
||||
const pathLast = schema.resourceMetadata.GetOperations[0].Path.split("/").pop() ?? "";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { ChoiceSchema, ChoiceValue, CodeModel, SchemaType, SealedChoiceSchema } from "@autorest/codemodel";
|
||||
import { getDataTypes } from "../data-types";
|
||||
import { TypespecChoiceValue, TypespecEnum } from "../interfaces";
|
||||
import { getEnumDecorators } from "../utils/decorators";
|
||||
import { getEnumChoiceClientDecorators, getEnumClientDecorators, getEnumDecorators } from "../utils/decorators";
|
||||
import { transformValue } from "../utils/values";
|
||||
|
||||
export function transformEnum(schema: SealedChoiceSchema | ChoiceSchema, codeModel: CodeModel): TypespecEnum {
|
||||
|
@ -12,6 +12,7 @@ export function transformEnum(schema: SealedChoiceSchema | ChoiceSchema, codeMod
|
|||
if (!typespecEnum) {
|
||||
typespecEnum = {
|
||||
decorators: getEnumDecorators(schema),
|
||||
clientDecorators: getEnumClientDecorators(schema),
|
||||
doc: schema.language.default.description,
|
||||
kind: "enum",
|
||||
name: schema.language.default.name.replace(/-/g, "_"),
|
||||
|
@ -36,6 +37,7 @@ function transformChoiceMember(member: ChoiceValue): TypespecChoiceValue {
|
|||
doc: member.language.default.description,
|
||||
name: member.language.default.name,
|
||||
value: transformValue(member.value),
|
||||
clientDecorators: getEnumChoiceClientDecorators(member),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,12 @@ import { get } from "lodash";
|
|||
import { getDataTypes } from "../data-types";
|
||||
import { TypespecObject, TypespecObjectProperty } from "../interfaces";
|
||||
import { addCorePageAlias } from "../utils/alias";
|
||||
import { getModelDecorators, getPropertyClientDecorators, getPropertyDecorators } from "../utils/decorators";
|
||||
import {
|
||||
getModelClientDecorators,
|
||||
getModelDecorators,
|
||||
getPropertyClientDecorators,
|
||||
getPropertyDecorators,
|
||||
} from "../utils/decorators";
|
||||
import { getDiscriminator, getOwnDiscriminator } from "../utils/discriminator";
|
||||
import { getLogger } from "../utils/logger";
|
||||
import {
|
||||
|
@ -89,6 +94,7 @@ export function transformObject(schema: ObjectSchema, codeModel: CodeModel): Typ
|
|||
extendedParents: getExtendedParents(schema),
|
||||
spreadParents: getSpreadParents(schema, codeModel),
|
||||
decorators: getModelDecorators(schema),
|
||||
clientDecorators: getModelClientDecorators(schema),
|
||||
};
|
||||
|
||||
addCorePageAlias(updatedVisited);
|
||||
|
|
|
@ -21,7 +21,7 @@ import {
|
|||
} from "../interfaces";
|
||||
import { transformDataType } from "../model";
|
||||
import { getOptions } from "../options";
|
||||
import { getPropertyDecorators } from "../utils/decorators";
|
||||
import { getOperationClientDecorators, getPropertyDecorators } from "../utils/decorators";
|
||||
import { getLogger } from "../utils/logger";
|
||||
import { getLanguageMetadata } from "../utils/metadata";
|
||||
import { isConstantSchema } from "../utils/schemas";
|
||||
|
@ -114,6 +114,7 @@ export function transformRequest(_request: Request, operation: Operation, codeMo
|
|||
doc,
|
||||
summary,
|
||||
parameters,
|
||||
clientDecorators: getOperationClientDecorators(operation),
|
||||
verb: transformVerb(requests?.[0].protocol),
|
||||
route: transformRoute(requests?.[0].protocol),
|
||||
responses: [...new Set(transformedResponses)],
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
import {
|
||||
ChoiceSchema,
|
||||
ObjectSchema,
|
||||
ChoiceValue,
|
||||
Parameter,
|
||||
Property,
|
||||
Schema,
|
||||
SchemaType,
|
||||
SealedChoiceSchema,
|
||||
SerializationStyle,
|
||||
Operation,
|
||||
isNumberSchema,
|
||||
} from "@autorest/codemodel";
|
||||
import { TypespecDecorator, DecoratorArgument } from "../interfaces";
|
||||
import { createCSharpNameDecorator } from "../pretransforms/rename-pretransform";
|
||||
import { getOwnDiscriminator } from "./discriminator";
|
||||
import { isSealedChoiceSchema, isStringSchema } from "./schemas";
|
||||
|
||||
|
@ -55,6 +58,15 @@ export function getModelDecorators(model: ObjectSchema): TypespecDecorator[] {
|
|||
return decorators;
|
||||
}
|
||||
|
||||
export function getModelClientDecorators(model: ObjectSchema): TypespecDecorator[] {
|
||||
const decorators: TypespecDecorator[] = [];
|
||||
|
||||
if (model.language.csharp?.name) {
|
||||
decorators.push(createCSharpNameDecorator(model));
|
||||
}
|
||||
return decorators;
|
||||
}
|
||||
|
||||
export function getPropertyDecorators(element: Property | Parameter): TypespecDecorator[] {
|
||||
const decorators: TypespecDecorator[] = [];
|
||||
|
||||
|
@ -153,6 +165,10 @@ export function getPropertyClientDecorators(element: Property | Parameter): Type
|
|||
});
|
||||
}
|
||||
|
||||
if (element.language.csharp?.name) {
|
||||
decorators.push(createCSharpNameDecorator(element));
|
||||
}
|
||||
|
||||
return decorators;
|
||||
}
|
||||
|
||||
|
@ -240,6 +256,35 @@ export function getEnumDecorators(enumeration: SealedChoiceSchema | ChoiceSchema
|
|||
|
||||
return decorators;
|
||||
}
|
||||
|
||||
export function getEnumClientDecorators(enumeration: SealedChoiceSchema | ChoiceSchema): TypespecDecorator[] {
|
||||
const decorators: TypespecDecorator[] = [];
|
||||
|
||||
if (enumeration.language.csharp?.name) {
|
||||
decorators.push(createCSharpNameDecorator(enumeration));
|
||||
}
|
||||
|
||||
return decorators;
|
||||
}
|
||||
|
||||
export function getEnumChoiceClientDecorators(enumChoice: ChoiceValue): TypespecDecorator[] {
|
||||
const decorators: TypespecDecorator[] = [];
|
||||
|
||||
if (enumChoice.language.csharp?.name) {
|
||||
decorators.push(createCSharpNameDecorator(enumChoice));
|
||||
}
|
||||
return decorators;
|
||||
}
|
||||
|
||||
export function getOperationClientDecorators(operation: Operation): TypespecDecorator[] {
|
||||
const decorators: TypespecDecorator[] = [];
|
||||
|
||||
if (operation.language.csharp?.name) {
|
||||
decorators.push(createCSharpNameDecorator(operation));
|
||||
}
|
||||
return decorators;
|
||||
}
|
||||
|
||||
export function generateDecorators(decorators: TypespecDecorator[] = []): string {
|
||||
const definitions: string[] = [];
|
||||
for (const decorator of decorators ?? []) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { TypespecProgram } from "../interfaces";
|
||||
import { TypespecDecorator, TypespecProgram } from "../interfaces";
|
||||
import { getOptions } from "../options";
|
||||
|
||||
type Imports = {
|
||||
|
@ -46,12 +46,36 @@ export function getModelsImports(program: TypespecProgram) {
|
|||
export function getClientImports(program: TypespecProgram) {
|
||||
const modules = new Set<string>();
|
||||
const namespaces = new Set<string>();
|
||||
const addImports = (decs: TypespecDecorator[] | undefined) => {
|
||||
for (const dec of decs ?? []) {
|
||||
dec.module && modules.add(`import "${dec.module}";`);
|
||||
dec.namespace && namespaces.add(`using ${dec.namespace};`);
|
||||
}
|
||||
};
|
||||
for (const model of program.models.objects) {
|
||||
addImports(model.clientDecorators);
|
||||
for (const property of model.properties) {
|
||||
for (const decorator of property.clientDecorators ?? []) {
|
||||
decorator.module && modules.add(`import "${decorator.module}";`);
|
||||
decorator.namespace && namespaces.add(`using ${decorator.namespace};`);
|
||||
}
|
||||
addImports(property.clientDecorators);
|
||||
}
|
||||
}
|
||||
|
||||
for (const model of program.models.enums) {
|
||||
addImports(model.clientDecorators);
|
||||
for (const choice of model.members) {
|
||||
addImports(choice.clientDecorators);
|
||||
}
|
||||
}
|
||||
|
||||
for (const resource of program.models.armResources) {
|
||||
addImports(resource.clientDecorators);
|
||||
for (const property of resource.properties) {
|
||||
addImports(property.clientDecorators);
|
||||
}
|
||||
for (const op of resource.resourceOperations) {
|
||||
addImports(op.clientDecorators);
|
||||
}
|
||||
for (const op of resource.normalOperations) {
|
||||
addImports(op.clientDecorators);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,12 @@ export interface _ArmPagingMetadata {
|
|||
NextLinkName: string;
|
||||
}
|
||||
|
||||
export interface Metadata {
|
||||
Resources: Record<string, ArmResource>;
|
||||
RenameMapping: Record<string, string>;
|
||||
OverrideOperationName: Record<string, string>;
|
||||
}
|
||||
|
||||
export interface ArmResource {
|
||||
Name: string;
|
||||
GetOperations: _ArmResourceOperation[];
|
||||
|
@ -46,7 +52,7 @@ export interface ArmResource {
|
|||
IsSingletonResource: boolean;
|
||||
}
|
||||
|
||||
let armResourceCache: Record<string, ArmResource> | undefined;
|
||||
let metadataCache: Metadata | undefined;
|
||||
|
||||
export interface OperationWithResourceOperationFlag extends Operation {
|
||||
isResourceOperation?: boolean;
|
||||
|
@ -118,19 +124,19 @@ export function getResourceExistOperation(resource: ArmResource): Operation | un
|
|||
}
|
||||
}
|
||||
|
||||
export function getArmResourcesMetadata(): Record<string, ArmResource> {
|
||||
if (armResourceCache) {
|
||||
return armResourceCache;
|
||||
export function getArmResourcesMetadata(): Metadata {
|
||||
if (metadataCache) {
|
||||
return metadataCache;
|
||||
}
|
||||
const session = getSession();
|
||||
const outputFolder: string = session.configuration["output-folder"] ?? "";
|
||||
|
||||
try {
|
||||
const content = readFileSync(join(outputFolder, "resources.json"), "utf-8");
|
||||
const { Resources }: { Resources: Record<string, ArmResource> } = JSON.parse(content);
|
||||
armResourceCache = Resources;
|
||||
const metadata: Metadata = JSON.parse(content);
|
||||
metadataCache = metadata;
|
||||
|
||||
return armResourceCache;
|
||||
return metadataCache;
|
||||
} catch (e) {
|
||||
throw new Error(`Failed to load resources.json from ${outputFolder} \n ${e}`);
|
||||
}
|
||||
|
@ -141,7 +147,8 @@ export interface ArmResourceSchema extends ObjectSchema {
|
|||
}
|
||||
|
||||
export function tagSchemaAsResource(schema: ObjectSchema): void {
|
||||
const resourcesMetadata = getArmResourcesMetadata();
|
||||
const metadata = getArmResourcesMetadata();
|
||||
const resourcesMetadata = metadata.Resources;
|
||||
|
||||
for (const resourceName in resourcesMetadata) {
|
||||
if (resourcesMetadata[resourceName].SwaggerModelName.toLowerCase() === schema.language.default.name.toLowerCase()) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче