@autorest/powershell
Version:
AutoRest PowerShell Cmdlet Generator
508 lines • 25.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Helper = void 0;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const schema_1 = require("../utils/schema");
const codemodel_1 = require("@autorest/codemodel");
const linq_1 = require("@azure-tools/linq");
const codegen_1 = require("@azure-tools/codegen");
class Helper {
constructor(useDateTimeOffset = false) {
this.useDateTimeOffset = useDateTimeOffset;
}
HasConstrains(schema) {
if (schema.minimum !== undefined || schema.maximum !== undefined || schema.maxLength !== undefined || schema.minLength !== undefined || schema.maxItems !== undefined || schema.minItems !== undefined || schema.multipleOf !== undefined || schema.pattern !== undefined || schema.uniqueItems !== undefined) {
return true;
}
return false;
}
HasConstantProperty(schema) {
const virtualProperties = this.GetAllPublicVirtualProperties(schema.language.default.virtualProperties);
return virtualProperties.filter(p => p.required && (p.property.schema.type === codemodel_1.SchemaType.Constant || this.IsConstantEnumProperty(p) || (p.property.schema.type === codemodel_1.SchemaType.Object && this.HasConstantProperty(p.property.schema)))).length > 0;
}
GetCsharpType(schema) {
let type = schema.type;
if (schema.type === codemodel_1.SchemaType.Integer || schema.type === codemodel_1.SchemaType.Number) {
type = type + schema.precision;
}
const offset = this.useDateTimeOffset ? 'Offset' : '';
const typeMap = new Map([
['integer', 'int'],
['integer32', 'int'],
['integer64', 'long'],
['number32', 'double'],
['number64', 'double'],
['number128', 'decimal'],
['boolean', 'bool'],
['string', 'string'],
['unixtime', 'System.DateTime'],
['credential', 'string'],
['byte-array', 'byte[]'],
['duration', 'System.TimeSpan'],
['uuid', 'System.Guid'],
['date-time', 'System.DateTime' + offset],
['date', 'System.DateTime'],
['binary', 'string'],
['uri', 'string'],
['arm-id', 'string']
]);
if (typeMap.has(type)) {
return typeMap.get(type);
}
return '';
}
isArraySchema(schema) {
return schema.type === codemodel_1.SchemaType.Array;
}
isDictionarySchema(schema) {
return schema.type === codemodel_1.SchemaType.Dictionary;
}
ShouldValidate(schema) {
if (!schema) {
return false;
}
const typesToValidate = new Array();
const validatedTypes = new Set();
typesToValidate.push(schema);
while (typesToValidate.length > 0) {
const modelToValidate = typesToValidate.pop();
if (!modelToValidate) {
continue;
}
else {
if (validatedTypes.has(modelToValidate)) {
continue;
}
validatedTypes.add(modelToValidate);
if (this.isArraySchema(modelToValidate) || this.isDictionarySchema(modelToValidate)) {
typesToValidate.push(modelToValidate.elementType);
}
else if ((0, codemodel_1.isObjectSchema)(modelToValidate)) {
const virtualProperties = modelToValidate.extensions && modelToValidate.extensions['x-ms-azure-resource'] ? (0, schema_1.getAllPublicVirtualPropertiesForSdkWithoutInherited)(modelToValidate.language.default.virtualProperties) : (0, schema_1.getAllPublicVirtualPropertiesForSdk)(modelToValidate.language.default.virtualProperties);
(0, linq_1.values)(virtualProperties).where(p => (0, codemodel_1.isObjectSchema)(p.property.schema)).forEach(cp => typesToValidate.push(cp.property.schema));
if ((0, linq_1.values)(virtualProperties).any(p => (p.required && p.property.schema.type !== codemodel_1.SchemaType.Constant && !this.IsConstantEnumProperty(p)) || this.HasConstrains(p.property.schema))) {
return true;
}
}
}
}
return false;
}
appendConstraintValidations(valueReference, sb, model) {
const schema = model;
if (schema.maximum !== undefined) {
const rule = schema.exclusiveMaximum ? 'ExclusiveMaximum' : 'InclusiveMaximum';
const cmp = schema.exclusiveMaximum ? '>=' : '>';
sb.push(`if (${valueReference} ${cmp} ${schema.maximum})`);
sb.push('{');
sb.push(` throw new Microsoft.Rest.ValidationException(Microsoft.Rest.ValidationRules.${rule}, "${valueReference.replace('this.', '')}", ${schema.maximum});`);
sb.push('}');
}
if (schema.minimum !== undefined) {
const rule = schema.exclusiveMinimum ? 'ExclusiveMinimum' : 'InclusiveMinimum';
const cmp = schema.exclusiveMinimum ? '<=' : '<';
sb.push(`if (${valueReference} ${cmp} ${schema.minimum})`);
sb.push('{');
sb.push(` throw new Microsoft.Rest.ValidationException(Microsoft.Rest.ValidationRules.${rule}, "${valueReference.replace('this.', '')}", ${schema.minimum});`);
sb.push('}');
}
if (schema.maxItems !== undefined) {
sb.push(`if (${valueReference}.Count > ${schema.maxItems})`);
sb.push('{');
sb.push(` throw new Microsoft.Rest.ValidationException(Microsoft.Rest.ValidationRules.MaxItems, "${valueReference.replace('this.', '')}", ${schema.maxItems});`);
sb.push('}');
}
if (schema.maxLength !== undefined) {
sb.push(`if (${valueReference}.Length > ${schema.maxLength})`);
sb.push('{');
sb.push(` throw new Microsoft.Rest.ValidationException(Microsoft.Rest.ValidationRules.MaxLength, "${valueReference.replace('this.', '')}", ${schema.maxLength});`);
sb.push('}');
}
if (schema.minLength !== undefined) {
sb.push(`if (${valueReference}.Length < ${schema.minLength})`);
sb.push('{');
sb.push(` throw new Microsoft.Rest.ValidationException(Microsoft.Rest.ValidationRules.MinLength, "${valueReference.replace('this.', '')}", ${schema.minLength});`);
sb.push('}');
}
if (schema.minItems !== undefined) {
sb.push(`if (${valueReference}.Count < ${schema.minItems})`);
sb.push('{');
sb.push(` throw new Microsoft.Rest.ValidationException(Microsoft.Rest.ValidationRules.MinItems, "${valueReference.replace('this.', '')}", ${schema.minItems});`);
sb.push('}');
}
if (schema.multipleOf !== undefined) {
sb.push(`if (${valueReference} % ${schema.multipleOf} != 0)`);
sb.push('{');
sb.push(` throw new Microsoft.Rest.ValidationException(Microsoft.Rest.ValidationRules.MultipleOf, "${valueReference.replace('this.', '')}", ${schema.multipleOf});`);
sb.push('}');
}
if (schema.pattern !== undefined) {
// eslint-disable-next-line
const constraintValue = "\"" + schema.pattern.replace(/\\/g, "\\\\").replace(/"/g, "\\\"") + "\"";
let condition = `!System.Text.RegularExpressions.Regex.IsMatch(${valueReference}, ${constraintValue})`;
if (schema.type === codemodel_1.SchemaType.Dictionary) {
condition = `!System.Linq.Enumerable.All(${valueReference}.Values, value => System.Text.RegularExpressions.Regex.IsMatch(value, ${constraintValue}))`;
}
sb.push(`if (${condition})`);
sb.push('{');
sb.push(` throw new Microsoft.Rest.ValidationException(Microsoft.Rest.ValidationRules.Pattern, "${valueReference.replace('this.', '')}", ${constraintValue});`);
sb.push('}');
}
if (schema.uniqueItems !== undefined && 'true' === schema.uniqueItems.toString()) {
sb.push(`if (${valueReference}.Count != System.Linq.Enumerable.Count(System.Linq.Enumerable.Distinct(${valueReference})))`);
sb.push('{');
sb.push(` throw new Microsoft.Rest.ValidationException(Microsoft.Rest.ValidationRules.UniqueItems, "${valueReference.replace('this.', '')}");`);
sb.push('}');
}
}
isKindOfString(schema, required = false) {
var _a;
if (schema.type === codemodel_1.SchemaType.String) {
return true;
}
else if (schema.type === codemodel_1.SchemaType.Constant && schema.valueType.type === codemodel_1.SchemaType.String) {
return true;
}
else if (schema.type === codemodel_1.SchemaType.Choice && schema.choiceType.type === codemodel_1.SchemaType.String) {
return true;
}
else if (schema.type === codemodel_1.SchemaType.SealedChoice && schema.choiceType.type === codemodel_1.SchemaType.String && (((_a = schema.extensions) === null || _a === void 0 ? void 0 : _a['x-ms-model-as-string']) === true || (required && schema.choices.length === 1))) {
return true;
}
// ToDo: we need to figure how to handle the case when schema type is enum
// Skip it since there is a bug in IsKindOfString in the csharp generator
// if (schema.type === SchemaType.Choice && (<ChoiceSchema>schema).choiceType.type === SchemaType.String) {
// return true;
// }
// if (schema.type === SchemaType.SealedChoice
// && (<ChoiceSchema>schema).choiceType.type === SchemaType.String) {
// // currently assume modelAsString true
// return true;
// }
return false;
}
PathParameterString(parameter, clientPrefix) {
var _a;
if (!['path', 'query'].includes((_a = parameter.protocol.http) === null || _a === void 0 ? void 0 : _a.in)) {
return '';
}
const prefix = parameter.implementation === 'Client' ? `this${clientPrefix}.` : '';
let res = '';
if (this.isKindOfString(parameter.schema, parameter.required)) {
res = `${prefix}${parameter.language.default.name}`;
}
else {
let serializationSettings = `this${clientPrefix}.SerializationSettings`;
if (this.IsValueType(parameter.schema.type)) {
if (parameter.schema.type === codemodel_1.SchemaType.Date) {
serializationSettings = 'new Microsoft.Rest.Serialization.DateJsonConverter()';
}
else if (parameter.schema.type === codemodel_1.SchemaType.DateTime && parameter.schema.format === 'date-time-rfc1123') {
serializationSettings = 'new Microsoft.Rest.Serialization.DateTimeRfc1123JsonConverter()';
}
else if (parameter.schema.type === codemodel_1.SchemaType.Uri) {
serializationSettings = 'new Microsoft.Rest.Serialization.Base64UrlJsonConverter()';
}
else if (parameter.schema.type === codemodel_1.SchemaType.UnixTime) {
serializationSettings = 'new Microsoft.Rest.Serialization.UnixTimeJsonConverter()';
}
}
res = `Microsoft.Rest.Serialization.SafeJsonConvert.SerializeObject(${prefix}${parameter.language.default.name}, ${serializationSettings}).Trim('"')`;
}
if (parameter.extensions && parameter.extensions['x-ms-skip-url-encoding']) {
return res;
}
else {
return `System.Uri.EscapeDataString(${res})`;
}
}
ValidateType(schema, scope, valueReference, isNullable, indentation = 3) {
const indentationSpaces = ' '.repeat(indentation);
const sb = new Array();
if (!scope) {
throw new Error('scope is null');
}
if (!!schema && (0, codemodel_1.isObjectSchema)(schema) && this.ShouldValidateChain(schema)) {
sb.push(`${valueReference}.Validate();`);
}
if (this.HasConstrains(schema)) {
this.appendConstraintValidations(valueReference, sb, schema);
}
if (schema && this.isArraySchema(schema) && this.ShouldValidateChain(schema)) {
// ToDo: Should try to get a unique name instead of element
let elementVar = 'element';
if (valueReference.startsWith(elementVar)) {
elementVar = valueReference + '1';
}
const innerValidation = this.ValidateType(schema.elementType, scope, elementVar, true, 1);
if (innerValidation) {
sb.push(`foreach (var ${elementVar} in ${valueReference})`);
sb.push('{');
innerValidation.split('\r\n').map(str => sb.push(str));
sb.push('}');
}
}
else if (schema && this.isDictionarySchema(schema) && this.ShouldValidateChain(schema)) {
// ToDo: Should try to get a unique name instead of valueElement
let valueVar = 'valueElement';
if (valueReference.startsWith(valueVar)) {
valueVar = valueReference + '1';
}
const innerValidation = this.ValidateType(schema.elementType, scope, valueVar, true, 1);
if (innerValidation) {
sb.push(`foreach (var ${valueVar} in ${valueReference}.Values)`);
sb.push('{');
innerValidation.split('\r\n').map(str => sb.push(str));
sb.push('}');
}
}
if (sb.length > 0) {
if (this.IsValueType(schema.type) && !isNullable) {
return sb.map(str => indentationSpaces + str).join('\r\n');
}
else {
return `${indentationSpaces}if (${valueReference} != null)\r\n${indentationSpaces}{\r\n${sb.map(str => indentationSpaces + ' ' + str).join('\r\n')}\r\n${indentationSpaces}}`;
}
}
return '';
}
ShouldValidateChain(schema) {
if (!schema) {
return false;
}
const typesToValidate = new Array();
const validatedTypes = new Set();
typesToValidate.push(schema);
while (typesToValidate.length > 0) {
const modelToValidate = typesToValidate.pop();
if (!modelToValidate) {
continue;
}
else {
validatedTypes.add(modelToValidate);
if (this.isArraySchema(modelToValidate) || this.isDictionarySchema(modelToValidate)) {
typesToValidate.push(modelToValidate.elementType);
}
else if ((0, codemodel_1.isObjectSchema)(modelToValidate)) {
if (this.ShouldValidate(modelToValidate)) {
return true;
}
if (modelToValidate.parents && (modelToValidate.parents.immediate.length === 1 && !(modelToValidate.extensions && modelToValidate.extensions['x-ms-azure-resource']))) {
typesToValidate.push(modelToValidate.parents.immediate[0]);
}
}
}
}
return false;
}
GetDeserializationSettings(schema, ref) {
if (schema.type === codemodel_1.SchemaType.Date) {
return 'new Microsoft.Rest.Serialization.DateJsonConverter()';
}
else if (schema.type === codemodel_1.SchemaType.Uri) {
return 'new Microsoft.Rest.Serialization.Base64UrlJsonConverter()';
}
else if (schema.type === codemodel_1.SchemaType.UnixTime) {
return 'new Microsoft.Rest.Serialization.UnixTimeJsonConverter()';
}
return ref + '.DeserializationSettings';
}
GetSerializationSettings(schema, ref) {
if (schema.type === codemodel_1.SchemaType.Date) {
return 'new Microsoft.Rest.Serialization.DateJsonConverter()';
}
else if (schema.type === codemodel_1.SchemaType.Uri) {
return 'new Microsoft.Rest.Serialization.Base64UrlJsonConverter()';
}
else if (schema.type === codemodel_1.SchemaType.UnixTime) {
return 'new Microsoft.Rest.Serialization.UnixTimeJsonConverter()';
}
return ref + '.SerializationSettings';
}
IsNullCheckRequiredForVirtualProperty(virtualProperty) {
return !((this.IsValueType(virtualProperty.property.schema.type) || (virtualProperty.property.schema.type === codemodel_1.SchemaType.SealedChoice && (virtualProperty.property.schema.choiceType.type !== codemodel_1.SchemaType.String || (virtualProperty.property.schema.extensions && !virtualProperty.property.schema.extensions['x-ms-model-as-string'])))) && (virtualProperty.required || virtualProperty.property.nullable === false));
}
CamelCase(str) {
// str = str.replace(/(?:^\w|[A-Z]|\b\w)/g, function (word, index) {
// return index === 0 ? word.toLowerCase() : word.toUpperCase();
// }).replace(/\s+/g, '');
return (0, codegen_1.camelCase)(str);
}
PascalCase(str) {
return (0, codegen_1.pascalCase)(str);
}
GetAllPublicVirtualProperties(virtualProperties) {
return (0, schema_1.getAllPublicVirtualPropertiesForSdk)(virtualProperties);
}
GetAllPublicVirtualPropertiesWithoutInherited(virtualProperties) {
return (0, schema_1.getAllPublicVirtualPropertiesForSdkWithoutInherited)(virtualProperties);
}
NeedsTransformationConverter(object) {
for (const property of (0, linq_1.values)(object.properties)) {
if (property.extensions && property.extensions['x-ms-client-flatten']) {
return true;
}
}
return false;
}
IsValueType(type) {
if (['boolean', 'integer', 'number', 'unixtime', 'duration', 'uuid', 'date-time', 'date'].includes(type)) {
return true;
}
return false;
}
HandleConstParameters(operation) {
const result = new Array();
const bodyParameters = operation.requests && operation.requests.length > 0 ? (operation.requests[0].parameters || []).filter(each => each.protocol.http && each.protocol.http.in === 'body' && !(each.extensions && each.extensions['x-ms-client-flatten']) && each.implementation !== 'Client') : [];
const nonBodyParameters = operation.parameters ? operation.parameters.filter(each => each.implementation !== 'Client') : [];
const parameters = [...nonBodyParameters, ...bodyParameters].filter(each => this.IsConstantEnumParameter(each));
for (const parameter of (0, linq_1.values)(parameters)) {
const quote = parameter.schema.choiceType.type === codemodel_1.SchemaType.String ? '"' : '';
const csharpType = this.GetCsharpType((parameter.schema).choiceType);
result.push(` ${csharpType} ${parameter.language.default.name} = ${quote}${parameter.schema.choices[0].value}${quote};`);
}
return result.join('\r\n');
}
IsConstantEnumParameter(parameter) {
if (!parameter.required) {
// const parameters are always required
return false;
}
// skip parameter.schema.type === SchemaType.Constant, since there is a bug
if ((parameter.schema.type === codemodel_1.SchemaType.SealedChoice && (parameter.schema).choices.length === 1)
|| (parameter.schema.type === codemodel_1.SchemaType.Choice && (parameter.schema).choices.length === 1)) {
return true;
}
return false;
}
IsConstantParameter(parameter) {
if (this.IsConstantEnumParameter(parameter)) {
return true;
}
if (parameter.schema.type === codemodel_1.SchemaType.Constant) {
return true;
}
return false;
}
IsConstantEnumProperty(property) {
if (!property.required) {
// const parameters are always required
return false;
}
// skip parameter.schema.type === SchemaType.Constant, since there is a bug
if ((property.property.schema.type === codemodel_1.SchemaType.SealedChoice && (property.property.schema).choices.length === 1)
|| (property.property.schema.type === codemodel_1.SchemaType.Choice && (property.property.schema).choices.length === 1)) {
return true;
}
return false;
}
IsConstantProperty(property) {
if (this.IsConstantEnumProperty(property)) {
return true;
}
if (property.property.schema.type === codemodel_1.SchemaType.Constant) {
return true;
}
return false;
}
GetUniqueName(name, usedNames) {
let uniqueName = name;
let i = 0;
while (usedNames.includes(uniqueName)) {
uniqueName = `${name}${++i}`;
}
return uniqueName;
}
GetValidCsharpName(name) {
let validChars = name.replace(/[^a-zA-Z0-9_]/g, '');
// prepend '_' if the name starts with a digit
if (!/^[a-zA-Z_]/.test(validChars)) {
validChars = '_' + validChars;
}
return validChars;
}
IsEnum(schema) {
if (schema.type === codemodel_1.SchemaType.SealedChoice && schema.choiceType.type === codemodel_1.SchemaType.String && schema.extensions && !schema.extensions['x-ms-model-as-string']) {
return true;
}
return false;
}
ConvertToValidMethodGroupKey(key) {
return key.replace(/Operations$/, '');
}
isCloudErrorName(name) {
// This is to work around the fact that some CloudError will be generated as CloudErrorAutoGenerated in m4
const reg = new RegExp('^CloudErrorAutoGenerated\\d{0,1}$');
if (name === 'CloudError' || reg.test(name)) {
return true;
}
return false;
}
IsCloudErrorException(operation) {
return (!operation.exceptions || !operation.exceptions[0].schema || this.isCloudErrorName(operation.exceptions[0].schema.language.default.name));
}
PopulateGroupParameters(parameter) {
var _a;
const groupParameter = parameter.language.default.name;
const result = Array();
for (const virtualProperty of (0, linq_1.values)((parameter.schema.language.default.virtualProperties.owned))) {
let type = ((_a = virtualProperty.property.schema.language.csharp) === null || _a === void 0 ? void 0 : _a.fullname) || '';
type = (this.IsValueType(virtualProperty.property.schema.type) || (virtualProperty.property.schema.type === codemodel_1.SchemaType.SealedChoice && virtualProperty.property.schema.choiceType.type === codemodel_1.SchemaType.String && virtualProperty.property.schema.extensions && !virtualProperty.property.schema.extensions['x-ms-model-as-string'])) && !virtualProperty.required ? `${type}?` : type;
const CamelName = (0, codegen_1.camelCase)(virtualProperty.name);
result.push(` ${type} ${CamelName} = default(${type});`);
result.push(` if (${groupParameter} != null)`);
result.push(' {');
result.push(` ${CamelName} = ${groupParameter}.${(0, codegen_1.pascalCase)(CamelName)};`);
result.push(' }');
}
if (result.length > 0) {
return result.join('\r\n');
}
return '';
}
wrapComments(indentation, prefix, comments) {
const defaultMaximumCommentColumns = 80;
if (comments === null || comments === undefined || comments.length === 0) {
return '';
}
//cannot predict indentation because we cannot get last line generated
const length = defaultMaximumCommentColumns - prefix.length - 1;
const result = this.lineBreak(comments, length);
for (let i = 0; i < result.length; i++) {
if (i != 0) {
result[i] = prefix + result[i];
}
}
return result.join('\n' + indentation);
}
lineBreak(comments, length) {
const splitter = /\r\n|\r|\n/i;
const lines = new Array();
for (const line of comments.split(splitter)) {
let processedLine = line;
while (processedLine.length > 0) {
processedLine = processedLine.trim();
const whiteSpacePositions = [...new Array(processedLine.length).keys()].filter(i => /\s/.test(processedLine[i])).concat([processedLine.length]);
let preWidthWrapAt = 0;
let postWidthWrapAt = 0;
for (const index of whiteSpacePositions) {
if (index <= length) {
preWidthWrapAt = index;
}
else if (postWidthWrapAt === 0) {
postWidthWrapAt = index;
}
}
const wrapAt = preWidthWrapAt != 0 ? preWidthWrapAt : (postWidthWrapAt != 0 ? postWidthWrapAt : processedLine.length);
lines.push(processedLine.substring(0, wrapAt));
processedLine = processedLine.substring(wrapAt);
}
}
return lines;
}
}
exports.Helper = Helper;
//# sourceMappingURL=utility.js.map