Skip to content

Commit

Permalink
Add the config fixed-array, which is false by default (#1385)
Browse files Browse the repository at this point in the history
  • Loading branch information
dolauli authored Oct 8, 2024
1 parent 81740c0 commit d9e6747
Show file tree
Hide file tree
Showing 9 changed files with 45 additions and 32 deletions.
40 changes: 22 additions & 18 deletions powershell/cmdlets/class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ export class CmdletClass extends Class {
};
}

const httpParamTD = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration((<NewSchema>httpParam.schema), httpParam.required, this.state);
const httpParamTD = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration((<NewSchema>httpParam.schema), httpParam.required, this.state, this.state.project.fixedArray);
return {
name: each.param,
expression: toExpression(`this.InvocationInformation.BoundParameters.ContainsKey("${each.param.value}") ? ${each.param.value} : ${httpParamTD.defaultOfType}`),
Expand Down Expand Up @@ -586,11 +586,13 @@ export class CmdletClass extends Class {

private WriteObjectWithViewControl(valueName: string, isEnumerable = false) {
const $this = this;
const lengthFunc = $this.state.project.fixedArray ? 'Length' : 'Count';
const listToArrayFunc = $this.state.project.fixedArray ? '.ToArray()' : '';
if ($this.state.project.autoSwitchView) {
if (isEnumerable) {
return function* () {
yield If(`null != ${valueName}`, function* () {
yield If(`0 == _responseSize && 1 == ${valueName}.Count`, function* () {
yield If(`0 == _responseSize && 1 == ${valueName}.${lengthFunc}`, function* () {
yield `_firstResponse = ${valueName}[0];`;
yield '_responseSize = 1;';
});
Expand All @@ -600,7 +602,7 @@ export class CmdletClass extends Class {
yield ForEach('value', valueName, function* () {
yield 'values.Add(value.AddMultipleTypeNameIntoPSObject());';
});
yield 'WriteObject(values, true); ';
yield `WriteObject(values${listToArrayFunc}, true); `;
yield '_responseSize = 2;';
});
});
Expand Down Expand Up @@ -993,7 +995,7 @@ export class CmdletClass extends Class {
const match = props.find(p => pascalCase(p.serializedName) === pascalName);
if (match) {

const defaultOfType = $this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(match.schema, true, $this.state).defaultOfType;
const defaultOfType = $this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(match.schema, true, $this.state, $this.state.project.fixedArray).defaultOfType;
// match up vp name
const vp = allVPs.find(pp => pascalCase(pp.property.serializedName) === pascalName);
//push path parameters that form current identity into allParams, idOpParamsFromIdentity and idOpParamsFromIdentityserializedName
Expand Down Expand Up @@ -1404,7 +1406,7 @@ export class CmdletClass extends Class {
if ('schema' in each) {
const schema = (<SchemaResponse>each).schema;
const props = NewGetAllPublicVirtualProperties(schema.language.csharp?.virtualProperties);
const rType = $this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(<NewSchema>schema, true, $this.state);
const rType = $this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(<NewSchema>schema, true, $this.state, $this.state.project.fixedArray);

const result = new LocalVariable('result', dotnet.Var, { initializer: new LiteralExpression('(await response)') });
yield `// (await response) // should be ${rType.declaration}`;
Expand All @@ -1428,13 +1430,15 @@ export class CmdletClass extends Class {
// write out the current contents
const vp = NewGetVirtualPropertyFromPropertyName(schema.language.csharp?.virtualProperties, valueProperty.serializedName);
if (vp) {
const lengthFunc = $this.state.project.fixedArray ? 'Length' : 'Count';
const subArrayFunc = $this.state.project.fixedArray ? 'SubArray' : 'GetRange';
if ($this.clientsidePagination) {
yield (If('(ulong)result.Value.Count <= this.PagingParameters.Skip', function* () {
yield ('this.PagingParameters.Skip = this.PagingParameters.Skip - (ulong)result.Value.Count;');
yield (If(`(ulong)result.Value.${lengthFunc} <= this.PagingParameters.Skip`, function* () {
yield (`this.PagingParameters.Skip = this.PagingParameters.Skip - (ulong)result.Value.${lengthFunc};`);
}));
yield Else(function* () {
yield ('ulong toRead = Math.Min(this.PagingParameters.First, (ulong)result.Value.Count - this.PagingParameters.Skip);');
yield ('var requiredResult = result.Value.GetRange((int)this.PagingParameters.Skip, (int)toRead);');
yield (`ulong toRead = Math.Min(this.PagingParameters.First, (ulong)result.Value.${lengthFunc} - this.PagingParameters.Skip);`);
yield (`var requiredResult = result.Value.${subArrayFunc}((int)this.PagingParameters.Skip, (int)toRead);`);
yield $this.WriteObjectWithViewControl('requiredResult', true);
yield ('this.PagingParameters.Skip = 0;');
yield ('this.PagingParameters.First = this.PagingParameters.First <= toRead ? 0 : this.PagingParameters.First - toRead;');
Expand Down Expand Up @@ -1772,7 +1776,7 @@ export class CmdletClass extends Class {
for (const parameter of values(operation.parameters)) {
// these are the parameters that this command expects
parameter.schema;
const td = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(<NewSchema>parameter.schema, true, this.state);
const td = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(<NewSchema>parameter.schema, true, this.state, this.state.project.fixedArray);

if (parameter.details.csharp.constantValue) {
// this parameter has a constant value -- SKIP IT
Expand Down Expand Up @@ -1831,12 +1835,12 @@ export class CmdletClass extends Class {
for (const vParam of vps.body) {
const vSchema = vParam.schema;
vParam.origin;
const propertyType = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(vSchema, true, this.state);
const propertyType = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(vSchema, true, this.state, this.state.project.fixedArray);

// we need to know if the actual underlying property is actually nullable.
const nullable = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(vSchema, !!(<NewVirtualProperty>vParam.origin).required, this.state).isNullable;
const nullable = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(vSchema, !!(<NewVirtualProperty>vParam.origin).required, this.state, this.state.project.fixedArray).isNullable;
let cmdletParameter: Property;
if (propertyType.schema.type !== SchemaType.Array) {
if (propertyType.schema.type !== SchemaType.Array || this.state.project.fixedArray) {
if (vParam.name === 'IdentityType' && !this.disableTransformIdentityType &&
(this.operation.commandType === CommandType.ManagedIdentityNew || this.operation.commandType === CommandType.ManagedIdentityUpdate)) {
const enableSystemAssignedIdentity = new Property('EnableSystemAssignedIdentity', operation.details.csharp.verb.toLowerCase() === 'new' ? SwitchParameter : NullableBoolean, {
Expand Down Expand Up @@ -1988,7 +1992,7 @@ export class CmdletClass extends Class {
declaration: parameter.schema.language.csharp?.fullname
},
valueType: (<DictionarySchema>paramDictSchema).elementType.type === SchemaType.Any ? System.Object :
this.state.project.schemaDefinitionResolver.resolveTypeDeclaration((<DictionarySchema>paramDictSchema).elementType, true, this.state)
this.state.project.schemaDefinitionResolver.resolveTypeDeclaration((<DictionarySchema>paramDictSchema).elementType, true, this.state, this.state.project.fixedArray)
};
}

Expand All @@ -2002,7 +2006,7 @@ export class CmdletClass extends Class {
this.inputObjectParameterName = `${this.name.split(viaIdentityRegex)[1].split('Expanded')[0]}InputObject`;
// add in the pipeline parameter for the identity
const idschema = values(this.state.project.model.schemas.objects).first(each => each.language.default.uid === 'universal-parameter-type');
const idtd = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(idschema, true, this.state);
const idtd = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(idschema, true, this.state, this.state.project.fixedArray);
const idParam = this.add(new BackedProperty(this.inputObjectParameterName, idtd, {
description: 'Identity Parameter'
}));
Expand All @@ -2025,7 +2029,7 @@ export class CmdletClass extends Class {
}));
} else {
const vSchema = vParam.schema;
propertyType = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(vSchema, true, this.state);
propertyType = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(vSchema, true, this.state, this.state.project.fixedArray);


origin = <NewIParameter>vParam.origin;
Expand Down Expand Up @@ -2198,7 +2202,7 @@ export class CmdletClass extends Class {
(resultSchema.type === SchemaType.SealedChoice && (<any>resultSchema).choiceType.type === SchemaType.Boolean && (<SealedChoiceSchema>resultSchema).choices.length === 1)) {
outputTypes.add(`typeof(${dotnet.Bool})`);
} else {
const typeDeclaration = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(resultSchema, true, this.state);
const typeDeclaration = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(resultSchema, true, this.state, this.state.project.fixedArray);

if (typeDeclaration.declaration === System.IO.Stream.declaration || typeDeclaration.declaration === dotnet.Binary.declaration) {
// if this is a stream, skip the output type.
Expand All @@ -2219,7 +2223,7 @@ export class CmdletClass extends Class {
}
const nestedSchema = ((<ObjectSchema>typeDeclaration.schema).properties?.find(p => p.serializedName === pageableInfo.itemName)
|| (<ObjectSchema>(<ObjectSchema>typeDeclaration.schema).parents?.all.find(s => isObjectSchema(s) && s.properties?.find((p => p.serializedName === pageableInfo.itemName)))).properties?.find((p => p.serializedName === pageableInfo.itemName)))?.schema;
const nestedTypeDeclaration = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(nestedSchema, true, this.state);
const nestedTypeDeclaration = this.state.project.schemaDefinitionResolver.resolveTypeDeclaration(nestedSchema, true, this.state, this.state.project.fixedArray);
type = (<ArrayOf>nestedTypeDeclaration).elementTypeDeclaration;
} else {
type = typeDeclaration.declaration;
Expand Down
6 changes: 5 additions & 1 deletion powershell/internal/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ export class Project extends codeDomProject {
public metadata!: Metadata;
public state!: State;
public helpLinkPrefix!: string;
public fixedArray!: boolean;
get model() {
return <PwshModel>this.state.model;
}
Expand All @@ -209,7 +210,7 @@ export class Project extends codeDomProject {
this.state.model = state.model;
}

this.schemaDefinitionResolver = new PSSchemaResolver();
this.schemaDefinitionResolver = new PSSchemaResolver(this.state.project.fixedArray);

this.projectNamespace = this.state.model.language.csharp?.namespace || '';

Expand Down Expand Up @@ -330,6 +331,9 @@ export class Project extends codeDomProject {
this.resourcesFolder = await this.state.getValue('resources-folder');
this.uxFolder = await this.state.getValue('ux-folder');

// configuration for whether to use fixed array in generated code of model, default is false
this.fixedArray = await this.state.getValue('fixed-array', false);

// File paths
this.csproj = await this.state.getValue('csproj');
this.dll = await this.state.getValue('dll');
Expand Down
6 changes: 3 additions & 3 deletions powershell/llcsharp/model/namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ class ApiVersionNamespace extends Namespace {
export class ModelsNamespace extends Namespace {
private subNamespaces = new Dictionary<Namespace>();

resolver = new SchemaDefinitionResolver();
newResolver = new SchemaDefinitionResolver();
resolver = new SchemaDefinitionResolver(this.state.project.fixedArray);
newResolver = new SchemaDefinitionResolver(this.state.project.fixedArray);
constructor(parent: Namespace, private schemas: NewSchemas, private state: State, objectInitializer?: DeepPartial<ModelsNamespace>) {
super('Models', parent);
this.subNamespaces[this.fullName] = this;
Expand Down Expand Up @@ -89,7 +89,7 @@ export class ModelsNamespace extends Namespace {
throw new Error('SCHEMA MISSING?');
}

const td = this.newResolver.resolveTypeDeclaration(schema, required, state);
const td = this.newResolver.resolveTypeDeclaration(schema, required, state, state.project.fixedArray);

if (!schema.language.csharp?.skip) {
if (td instanceof ObjectImplementation) {
Expand Down
3 changes: 3 additions & 0 deletions powershell/llcsharp/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export class Project extends codeDomProject {
identityCorrection!: boolean;
resourceGroupAppend!: boolean;
supportJsonInput!: boolean;
fixedArray!: boolean;
formats!: Dictionary<PropertyFormat>;

constructor(protected service: Host | TspHost, objectInitializer?: DeepPartial<Project>) {
Expand Down Expand Up @@ -67,6 +68,8 @@ export class Project extends codeDomProject {
}
this.enableApiRetry = await this.state.getValue('enable-api-retry', true);

// configuration for whether to use fixed array in generated code of model, default is false
this.fixedArray = await this.state.getValue('fixed-array', false);

// add project namespace
this.projectNamespace = this.state.model.language.csharp?.namespace;
Expand Down
6 changes: 5 additions & 1 deletion powershell/llcsharp/schema/schema-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,15 @@ import { Password } from './password';

export class SchemaDefinitionResolver {
private readonly cache = new Map<string, EnhancedTypeDeclaration>();
private fixedArrayConfig: boolean;
private add(schema: NewSchema, value: EnhancedTypeDeclaration): EnhancedTypeDeclaration {
this.cache.set(schema.language?.csharp?.fullname || '', value);
return value;
}

constructor(fixedArrayConfig: boolean) {
this.fixedArrayConfig = fixedArrayConfig;
}
// isFixedArray is used to determine if we want to use a fixed array or not
resolveTypeDeclaration(schema: NewSchema | undefined, required: boolean, state: ModelState<CodeModel>, isFixedArray?: boolean): EnhancedTypeDeclaration {
if (!schema) {
Expand All @@ -49,7 +53,7 @@ export class SchemaDefinitionResolver {
// can be recursive!
// handle boolean arrays as booleans (powershell will try to turn it into switches!)
const ar = <ArraySchema>schema;
const elementType = (ar.elementType.type === SchemaType.Boolean) ? new Boolean(<BooleanSchema>schema, true) : this.resolveTypeDeclaration(ar.elementType, true, state.path('items'));
const elementType = (ar.elementType.type === SchemaType.Boolean) ? new Boolean(<BooleanSchema>schema, true) : this.resolveTypeDeclaration(ar.elementType, true, state.path('items'), this.fixedArrayConfig);
if (isFixedArray) {
return new FixedArrayOf(schema, required, elementType, ar.minItems, ar.maxItems, ar.uniqueItems);
} else {
Expand Down
6 changes: 3 additions & 3 deletions powershell/models/model-extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class ModelExtensionsNamespace extends Namespace {
public get outputFolder(): string {
return join(this.state.project.apiFolder, 'Models');
}
resolver = new SchemaDefinitionResolver();
resolver = new SchemaDefinitionResolver(this.state.project.fixedArray);

constructor(parent: Namespace, private schemas: Dictionary<Array<NewSchema>>, private state: State, objectInitializer?: DeepPartial<ModelExtensionsNamespace>) {
super('Models', parent);
Expand All @@ -44,7 +44,7 @@ export class ModelExtensionsNamespace extends Namespace {


const $this = this;
const resolver = (s: NewSchema, req: boolean) => this.resolver.resolveTypeDeclaration(s, req, state);
const resolver = (s: NewSchema, req: boolean) => this.resolver.resolveTypeDeclaration(s, req, state, state.project.fixedArray);

// Add typeconverters to model classes (partial)
for (const schemaGroup of values(schemas)) {
Expand All @@ -53,7 +53,7 @@ export class ModelExtensionsNamespace extends Namespace {
continue;
}

const td = this.resolver.resolveTypeDeclaration(schema, true, state);
const td = this.resolver.resolveTypeDeclaration(schema, true, state, state.project.fixedArray);
if (td instanceof ObjectImplementation) {

// it's a class object.
Expand Down
8 changes: 4 additions & 4 deletions powershell/plugins/cs-namer-v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { codeModelSchema, SchemaResponse, CodeModel, Schema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, StringSchema, ChoiceSchema, SealedChoiceSchema } from '@autorest/codemodel';
import { camelCase, deconstruct, excludeXDash, fixLeadingNumber, pascalCase, lowest, maximum, minimum, getPascalIdentifier, serialize } from '@azure-tools/codegen';
import { items, values, keys, Dictionary, length } from '@azure-tools/linq';
import { System } from '@azure-tools/codegen-csharp';
import { Project, System } from '@azure-tools/codegen-csharp';

import { Channel, AutorestExtensionHost as Host, Session, startSession } from '@autorest/extension-base';
import { SchemaDetails } from '../llcsharp/code-model';
Expand Down Expand Up @@ -210,9 +210,9 @@ async function setOperationNames(state: State, resolver: SchemaDefinitionResolve
for (const rsp of responses) {
// per responseCode
const response = <SchemaResponse>rsp;
const responseTypeDefinition = response.schema ? resolver.resolveTypeDeclaration(<any>response.schema, true, state) : undefined;
const responseTypeDefinition = response.schema ? resolver.resolveTypeDeclaration(<any>response.schema, true, state, await state.getValue('fixed-array', false)) : undefined;
const headerSchema = response.language.default.headerSchema;
const headerTypeDefinition = headerSchema ? resolver.resolveTypeDeclaration(<any>headerSchema, true, state.path('schemas', headerSchema.language.default.name)) : undefined;
const headerTypeDefinition = headerSchema ? resolver.resolveTypeDeclaration(<any>headerSchema, true, state.path('schemas', headerSchema.language.default.name), await state.getValue('fixed-array', false)) : undefined;
let code = (System.Net.HttpStatusCode[response.protocol.http?.statusCodes[0]] ? System.Net.HttpStatusCode[response.protocol.http?.statusCodes[0]].value : (response.protocol.http?.statusCodes[0] || '')).replace('global::System.Net.HttpStatusCode', '');
let rawValue = code.replace(/\./, '');
if (response.protocol.http?.statusCodes[0] === 'default' || rawValue === 'default' || '') {
Expand All @@ -238,7 +238,7 @@ async function setOperationNames(state: State, resolver: SchemaDefinitionResolve
}

export async function nameStuffRight(state: State): Promise<PwshModel> {
const resolver = new SchemaDefinitionResolver();
const resolver = new SchemaDefinitionResolver(await state.getValue('fixed-array', false));
const model = state.model;

// set the namespace for the service
Expand Down
1 change: 0 additions & 1 deletion powershell/plugins/sdk-cs-namer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,6 @@ function correctParameterNames(model: SdkModel) {
async function nameStuffRight(state: State): Promise<SdkModel> {
const useDateTimeOffset = await state.getValue('useDateTimeOffset', false);
const helper = new Helper(useDateTimeOffset);
const resolver = new SchemaDefinitionResolver();
const model = state.model;

// set the namespace for the service
Expand Down
Loading

0 comments on commit d9e6747

Please sign in to comment.