powershell/llcsharp/schema/string.ts (174 lines of code) (raw):

/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { KnownMediaType } from '@azure-tools/codemodel-v3'; import { camelCase, deconstruct, nameof } from '@azure-tools/codegen'; import { System } from '@azure-tools/codegen-csharp'; import { Expression, ExpressionOrLiteral, toExpression, valueOf } from '@azure-tools/codegen-csharp'; import { If } from '@azure-tools/codegen-csharp'; import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { ChoiceSchema, Schema as NewSchema, SchemaType, SealedChoiceSchema, StringSchema } from '@autorest/codemodel'; import { popTempVar, pushTempVar } from './primitive'; import { EnhancedTypeDeclaration } from './extended-type-declaration'; import { length } from '@azure-tools/linq'; /** A ETD for the c# string type. */ export class String implements EnhancedTypeDeclaration { public isXmlAttribute = false; get defaultOfType() { return toExpression('null'); } get convertObjectMethod() { return 'global::System.Convert.ToString'; } get isNullable(): boolean { return true; } get encode(): string { return this.schema.extensions && this.schema.extensions['x-ms-skip-url-encoding'] ? '' : 'global::System.Uri.EscapeDataString'; } deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { switch (mediaType) { case KnownMediaType.Json: { // container should be a JsonObject const tmpVar = `__${camelCase(['json', ...deconstruct(serializedName)])}`; return toExpression(`If( ${valueOf(container)}?.PropertyT<${ClientRuntime.JsonString}>("${serializedName}"), out var ${tmpVar}) ? (string)${tmpVar} : (string)${defaultValue}`); } case KnownMediaType.Xml: { const xTmp = `__${camelCase(['xml', ...deconstruct(serializedName)])}`; return toExpression(`If( ${valueOf(container)}?.Element("${serializedName}"), out var ${xTmp}) ? (string)${xTmp} : (string)${defaultValue}`); } case KnownMediaType.Header: { // HttpResponseHeaders const tmp = `__${camelCase(['header', ...deconstruct(serializedName)])}`; return toExpression(`System.Linq.Enumerable.FirstOrDefault(${serializedName}) is string ${tmp} ? ${tmp} : (string)${defaultValue}`); } } return toExpression(`${defaultValue} /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename}*/`); } deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { try { const tmp = pushTempVar(); switch (mediaType) { case KnownMediaType.Json: // node should be a JsonString return toExpression(`${node} is ${ClientRuntime.JsonString} ${tmp} ? (${this.declaration})(${tmp}.ToString()) : ${defaultValue}`); case KnownMediaType.Xml: return toExpression(`${node} is ${System.Xml.Linq.XElement} ${tmp} ? (string)${tmp} : ${defaultValue}`); } } finally { popTempVar(); } return toExpression(`null /* deserializeFromContainer doesn't support '${mediaType}' ${__filename}*/`); } /** emits an expression serialize this to a HttpContent */ serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { return toExpression(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`); } serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { switch (mediaType) { case KnownMediaType.Json: return toExpression(`null != (((object)${value})?.ToString()) ? (${ClientRuntime.JsonNode}) new ${ClientRuntime.JsonString}(${value}.ToString()) : null`); case KnownMediaType.Xml: return toExpression(`null != (${value}?.ToString()) ? new ${System.Xml.Linq.XElement}("${serializedName}",${value}) : null`); case KnownMediaType.QueryParameter: { const formatSerializedName = serializedName ? `${serializedName}=` : ''; if (this.isRequired) { return toExpression(`"${formatSerializedName}" + ${this.encode}(${value})`); } else { return toExpression(`(string.IsNullOrEmpty(${value}) ? ${System.String.Empty} : "${formatSerializedName}" + ${this.encode}(${valueOf(value)}))`); } } case KnownMediaType.Cookie: case KnownMediaType.Header: case KnownMediaType.Text: case KnownMediaType.UriParameter: if (this.isRequired) { return toExpression(`${this.encode}(${value})`); } return toExpression(`(string.IsNullOrEmpty(${value}) ? ${System.String.Empty} : ${this.encode}(${value}) )`); } return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); } /** emits an expression to deserialize content from a string */ deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { switch (mediaType) { case KnownMediaType.Json: { return this.deserializeFromNode(mediaType, ClientRuntime.JsonNode.Parse(content), defaultValue); } case KnownMediaType.Xml: { return this.deserializeFromNode(mediaType, `${System.Xml.Linq.XElement}.Parse(${content})`, defaultValue); } case KnownMediaType.UriParameter: { return toExpression(content); } } return toExpression(`null /* deserializeFromString doesn't support '${mediaType}' ${__filename}`); } /** emits an expression to deserialize content from a content/response */ deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { switch (mediaType) { case KnownMediaType.Json: return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => body.Result)`); } return toExpression(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`); } serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { const formatSerializedName = serializedName ? `${serializedName}=` : ''; switch (mediaType) { case KnownMediaType.Json: return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, "${serializedName}" ,${container}.Add );`; case KnownMediaType.Xml: return `AddIf( ${this.serializeToNode(mediaType, value, serializedName, mode)}, ${container}.Add );`; case KnownMediaType.Header: // container : HttpRequestHeaders return this.isRequired ? `${valueOf(container)}.Add("${serializedName}",${value}.ToString());` : If(`null != ${value}`, `${valueOf(container)}.Add("${serializedName}",${value});`); case KnownMediaType.QueryParameter: // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter return this.isRequired ? `${formatSerializedName}{${value}.ToString()}` : `{null == ${value} ? ${System.String.Empty} : $"${formatSerializedName}{${value}.ToString()}"}`; case KnownMediaType.UriParameter: // gives a name=value for use inside a c# template string($"foo{someProperty}") as a query parameter return this.isRequired ? `(${formatSerializedName}{${value}.ToString()})` : `(null == ${value} ? ${System.String.Empty}: $"${formatSerializedName}{${value}.ToString()}")`; } return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`); } constructor(public schema: NewSchema, public isRequired: boolean) { } get declaration(): string { return 'string'; } validateValue(eventListener: Variable, property: Variable): string { return ` ${this.validateMinLength(eventListener, property)} ${this.validateMaxLength(eventListener, property)} ${this.validateRegex(eventListener, property)} ${this.validateEnum(eventListener, property)} `.trim(); } public validatePresence(eventListener: Variable, property: Variable): string { return `await ${eventListener}.AssertNotNull(${nameof(property.value)},${property});`.trim(); } private validateMinLength(eventListener: Variable, property: Variable): string { const len = (<any>this.schema).minLength; if (!len) { return ''; } return `await ${eventListener}.AssertMinimumLength(${nameof(property.value)},${property},${len});`; } private validateMaxLength(eventListener: Variable, property: Variable): string { const len = (<any>this.schema).maxLength; if (!len) { return ''; } return `await ${eventListener}.AssertMaximumLength(${nameof(property.value)},${property},${len});`; } private validateRegex(eventListener: Variable, property: Variable): string { const pattern = (<any>this.schema).pattern?.replace(/"/g, '""'); if (!pattern) { return ''; } return `await ${eventListener}.AssertRegEx(${nameof(property.value)}, ${property}, @"${pattern}");`; } private validateEnum(eventListener: Variable, property: Variable): string { if (this.schema.type !== SchemaType.SealedChoice && this.schema.type != SchemaType.Choice) { return ''; } const choiceValues = (<SealedChoiceSchema>this.schema).choices.map((c) => c.value); return `await ${eventListener}.AssertEnum(${nameof(property.value)},${property},${choiceValues.joinWith((v) => `@"${v}"`)});`; } }