Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions powershell/internal/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { codemodel, PropertyDetails, exportedModels as T, ModelState, JsonType,
import { DeepPartial } from '@azure-tools/codegen';
import { PwshModel } from '../utils/PwshModel';
import { NewModelState } from '../utils/model-state';
import { BooleanSchema, Schema as NewSchema, SchemaType } from '@azure-tools/codemodel';
import { BooleanSchema, ConstantSchema, Schema as NewSchema, SchemaType } from '@azure-tools/codemodel';

export type Schema = T.SchemaT<LanguageDetails<SchemaDetails>, LanguageDetails<PropertyDetails>>;

Expand Down Expand Up @@ -72,7 +72,7 @@ export class NewPSSchemaResolver extends NewSchemaDefinitionResolver {
try {
if (!this.inResolve) {
this.inResolve = true;
if (schema && schema.type === SchemaType.Boolean) {
if (schema && (schema.type === SchemaType.Boolean || (schema.type === SchemaType.Constant && (<ConstantSchema>schema).valueType.type === SchemaType.Boolean))) {
return new NewPSSwitch(<BooleanSchema>schema, required);
}
}
Expand Down
4 changes: 2 additions & 2 deletions powershell/llcsharp/schema/date-time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { OneOrMoreStatements } from '@azure-tools/codegen-csharp';
import { Variable } from '@azure-tools/codegen-csharp';
import { ClientRuntime } from '../clientruntime';
import { Schema } from '../code-model';
import { Schema as NewSchema, DateTimeSchema, UnixTimeSchema } from '@azure-tools/codemodel';
import { Schema as NewSchema, DateTimeSchema, UnixTimeSchema, DateSchema } from '@azure-tools/codemodel';
import { Primitive, NewPrimitive } from './primitive';

export class DateTime extends Primitive {
Expand Down Expand Up @@ -183,7 +183,7 @@ export class NewDateTime extends NewPrimitive {
}
return (`/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`);
}
constructor(schema: DateTimeSchema, public isRequired: boolean) {
constructor(schema: DateTimeSchema | DateSchema, public isRequired: boolean) {
super(schema);
}
// public static string DateFormat = "yyyy-MM-dd";
Expand Down
4 changes: 2 additions & 2 deletions powershell/llcsharp/schema/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { StringExpression } from '@azure-tools/codegen-csharp';
import { Schema } from '../code-model';
import { Schema as NewSchema, DateTimeSchema } from '@azure-tools/codemodel';
import { DateSchema } from '@azure-tools/codemodel';
import { DateTime, NewDateTime } from './date-time';

export class Date extends DateTime {
Expand All @@ -17,7 +17,7 @@ export class Date extends DateTime {

export class NewDate extends NewDateTime {
public DateTimeFormat = new StringExpression('yyyy-MM-dd');
constructor(schema: DateTimeSchema, isRequired: boolean) {
constructor(schema: DateSchema, isRequired: boolean) {
super(schema, isRequired);
}
}
23 changes: 9 additions & 14 deletions powershell/llcsharp/schema/schema-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { codeModelSchema, ArraySchema, CodeModel, Schema as NewSchema, StringSchema, BooleanSchema, NumberSchema, ByteArraySchema, DateTimeSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ConstantSchema, ChoiceSchema, DurationSchema } from '@azure-tools/codemodel';
import { codeModelSchema, ArraySchema, CodeModel, Schema as NewSchema, StringSchema, BooleanSchema, NumberSchema, ByteArraySchema, DateTimeSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ConstantSchema, ChoiceSchema, DurationSchema, BinarySchema, DateSchema } from '@azure-tools/codemodel';

import { ModelState, codemodel, IntegerFormat, NumberFormat, StringFormat, JsonType } from '@azure-tools/codemodel-v3';
import { Schema } from '../code-model';
Expand Down Expand Up @@ -189,6 +189,8 @@ export class NewSchemaDefinitionResolver {
return new NewString(<StringSchema>schema, required);

}
case SchemaType.Binary:
return new NewBinary(<BinarySchema>schema, required);
case SchemaType.Duration:
return new NewDuration(<DurationSchema>schema, required);
case SchemaType.Uuid:
Expand All @@ -198,6 +200,8 @@ export class NewSchemaDefinitionResolver {
return new NewDateTime1123(<DateTimeSchema>schema, required);
}
return new NewDateTime(<DateTimeSchema>schema, required);
case SchemaType.Date:
return new NewDate(<DateSchema>schema, required);
case SchemaType.ByteArray:
return new NewByteArray(<ByteArraySchema>schema, required);
case SchemaType.Boolean:
Expand All @@ -210,6 +214,7 @@ export class NewSchemaDefinitionResolver {
// skip-for-time-being
// case IntegerFormat.UnixTime:
// return new UnixTime(schema, required);
case 16:
case 32:
return new NewNumeric(<NumberSchema>schema, required, required ? 'int' : 'int?');
}
Expand All @@ -229,18 +234,8 @@ export class NewSchemaDefinitionResolver {
return new NewNumeric(<NumberSchema>schema, required, required ? 'float' : 'float?');

case SchemaType.Constant:
switch ((<ConstantSchema>schema).valueType.type) {
case SchemaType.String:
return new NewString(schema, required);
case SchemaType.DateTime:
if ((<any>schema).valueType.format === StringFormat.DateTimeRfc1123) {
return new NewDateTime1123(<DateTimeSchema>schema, required);
}
return new NewDateTime(<DateTimeSchema>schema, required);
default:
state.error(`Unsupported constant type. Schema '${schema.language.csharp?.name}' is declared with invalid type '${schema.type}'`, message.UnknownJsonType);
throw new Error('Unknown Model. Fatal.');
}
return this.resolveTypeDeclaration((<ConstantSchema>schema).valueType, required, state);

case SchemaType.Choice: {
const choiceSchema = schema as ChoiceSchema;
if ((<any>choiceSchema.choiceType).type === SchemaType.DateTime && (<any>choiceSchema.choiceType).format === StringFormat.DateTimeRfc1123) {
Expand All @@ -263,4 +258,4 @@ export class NewSchemaDefinitionResolver {
state.error(`Schema '${schema.language.csharp?.name}' is declared with invalid type '${schema.type}'`, message.UnknownJsonType);
throw new Error('Unknown Model. Fatal.');
}
}
}
51 changes: 0 additions & 51 deletions powershell/models/model-extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,57 +284,6 @@ export class NewModelExtensionsNamespace extends Namespace {
continue;
}

if (schema.type === SchemaType.Dictionary) {
// xichen:
// Case1: dictionary schema is only used in parents:
// "definitions": {
// "PetAPInPropertiesWithAPString": {
// "type": "object",
// "properties": {
// "id": {
// "type": "integer"
// }
// },
// "additionalProperties": {
// "type": "string"
// }
// }
// }
//
// Case2: we will have a dictionary property:
// "definitions": {
// "PetAPInProperties": {
// "type": "object",
// "properties": {
// "id": {
// "type": "integer"
// },
// "additionalProperties": {
// "type": "object",
// "additionalProperties": {
// "type": "number"
// }
// }
// }
// }
// }
//
// We only create model class for case 2, because in m3 case 2 will has independent scheam for additionalProperties,
// But for case 1, PetAPInPropertiesWithAPString will only have additionalProperties.
//
// This is to make generated code same as m3. Actually there wont be side effect if we skip this check.
const objSchemas = schemas['objects'];
const usedByProp = schemas['objects']?.some((objSchema) => {
if ((<ObjectSchema>objSchema).properties?.some((prop) => prop.schema === schema)) {
return true;
}
return false;
});
if (!usedByProp) {
continue;
}
}

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

Expand Down
4 changes: 2 additions & 2 deletions powershell/plugins/create-commands-v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,8 @@ export /* @internal */ class Inferrer {
}));

// let's add a variant where it's expanded out.
// *IF* the body is an object
if (body.schema.type === SchemaType.Object) {
// *IF* the body is an object or dictionary
if (body.schema.type === SchemaType.Object || body.schema.type === SchemaType.Dictionary) {
const opExpanded = await this.addCommandOperation(`${vname}Expanded`, parameters, operation, variant, state);
opExpanded.details.default.dropBodyParameter = true;
opExpanded.parameters.push(new IParameter(`${bodyParameterName}Body`, body.schema, {
Expand Down
4 changes: 2 additions & 2 deletions powershell/plugins/cs-namer-v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,14 +179,14 @@ async function setOperationNames(state: State, resolver: NewSchemaDefinitionReso

operation.language.csharp = {
...details, // inherit
name: getPascalIdentifier(operationName),
name: operationName,
};

// parameters are camelCased.
for (const parameter of values(operation.parameters)) {
const parameterDetails = parameter.language.default;

let propName = camelCase(fixLeadingNumber(deconstruct(parameterDetails.name)));
let propName = camelCase(fixLeadingNumber(deconstruct(parameterDetails.serializedName)));

if (propName === 'default') {
propName = '@default';
Expand Down
55 changes: 33 additions & 22 deletions powershell/plugins/plugin-tweak-m4-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { CodeModel, DictionarySchema, getAllProperties, HttpHeader, ObjectSchema, Property, Schema, SchemaType } from '@azure-tools/codemodel';
import { ArraySchema, CodeModel, DictionarySchema, getAllProperties, HttpHeader, ObjectSchema, Property, Schema, SchemaType } from '@azure-tools/codemodel';
import { serialize } from '@azure-tools/codegen';
import { PwshModel } from '../utils/PwshModel';
import { NewModelState } from '../utils/model-state';
Expand All @@ -19,7 +19,7 @@ async function tweakModel(state: State): Promise<PwshModel> {

addDictionaryApiVersion(model);

removeDictionaryDefaultDescription(model);
removeM4DefaultDescription(model);

return model;
}
Expand Down Expand Up @@ -80,62 +80,73 @@ function addResponseHeaderSchema(model: CodeModel) {
}

function addDictionaryApiVersion(model: CodeModel) {
// If object has dictionary property, this property's schema does not have api version information in m4. We should add this back.

model.schemas.dictionaries?.forEach((schema) => {
if (schema.apiVersions) {
return;
}
if (schema.elementType && schema.elementType.apiVersions) {
schema.apiVersions = JSON.parse(JSON.stringify(schema.elementType.apiVersions));
}
})

// If we cannot find api version from element type, try to get it from object schema who refers the dict or any.

model.schemas.objects?.forEach((schema) => {
if (!schema.apiVersions) {
return;
}

for (const prop of getAllProperties(schema)) {
if ((prop.schema.type !== SchemaType.Dictionary && prop.schema.type !== SchemaType.Any) || prop.schema.apiVersions) {
if (prop.schema.type !== SchemaType.Dictionary || prop.schema.apiVersions) {
continue;
}
const dictSchema = prop.schema as DictionarySchema;
if (dictSchema.elementType && dictSchema.elementType.apiVersions) {
dictSchema.apiVersions = JSON.parse(JSON.stringify(dictSchema.elementType.apiVersions));
} else {
dictSchema.apiVersions = JSON.parse(JSON.stringify(schema.apiVersions));
}
prop.schema.apiVersions = JSON.parse(JSON.stringify(schema.apiVersions));
}
})
}

function removeDictionaryDefaultDescription(model: CodeModel) {
// For dictionary schema and property, if there is no description assigned, m4 will set a default description like: Dictionary of <type>
function removeM4DefaultDescription(model: CodeModel) {
// For dictionary and arrya schema and property, if there is no description assigned, m4 will set a default description like: Dictionary of <type> or Array of <type>
// To keep same action as m3, we will set it to empty string

const visited = new Set<Schema>();
[...model.schemas.objects ?? [], ...model.schemas.dictionaries ?? []].forEach((schema) => {
recursiveRemoveDefaultDescription(schema, visited);
[...model.schemas.objects ?? [], ...model.schemas.dictionaries ?? [], ...model.schemas.arrays ?? []].forEach((schema) => {
recursiveRemoveM4DefaultDescription(schema, visited);
})
}

function recursiveRemoveDefaultDescription(schema: Schema, visited: Set<Schema>) {
if (visited.has(schema) || (schema.type !== SchemaType.Object && schema.type !== SchemaType.Dictionary)) {
function recursiveRemoveM4DefaultDescription(schema: Schema, visited: Set<Schema>) {
if (visited.has(schema) || (schema.type !== SchemaType.Object && schema.type !== SchemaType.Dictionary && schema.type !== SchemaType.Array)) {
return;
}
// Default description pattern in m4
const defaultDescPattern = /Dictionary of <.*>$/;
const defaultDictDescPattern = /Dictionary of <.?>$/;
const defaultArrayDescPattern = /Array of .?$/;
visited.add(schema);
if (schema.type === SchemaType.Dictionary) {
const dictSchema = schema as DictionarySchema;
recursiveRemoveDefaultDescription(dictSchema.elementType, visited);
if (defaultDescPattern.test(dictSchema.language.default.description)) {
recursiveRemoveM4DefaultDescription(dictSchema.elementType, visited);
if (defaultDictDescPattern.test(dictSchema.language.default.description)) {
dictSchema.language.default.description = '';
}
} else if (schema.type === SchemaType.Array) {
const arrSchema = schema as ArraySchema;
recursiveRemoveM4DefaultDescription(arrSchema.elementType, visited);
if (defaultArrayDescPattern.test(schema.language.default.description)) {
schema.language.default.description = '';
}
} else if (schema.type === SchemaType.Object) {
const objSchema = schema as ObjectSchema;
for (const prop of getAllProperties(objSchema)) {
recursiveRemoveDefaultDescription(prop.schema, visited);
if (prop.schema.type === SchemaType.Dictionary && defaultDescPattern.test(prop.language.default.description)) {
recursiveRemoveM4DefaultDescription(prop.schema, visited);
if (prop.schema.type === SchemaType.Dictionary && (defaultDictDescPattern.test(prop.language.default.description) || defaultArrayDescPattern.test(prop.language.default.description))) {
prop.language.default.description = '';
}
}
}
}


export async function tweakM4ModelPlugin(service: Host) {
const state = await new NewModelState<PwshModel>(service).init();
service.WriteFile('code-model-v4-tweakm4codemodel.yaml', serialize(await tweakModel(state)), undefined, 'code-model-v4');
Expand Down
34 changes: 22 additions & 12 deletions powershell/plugins/plugin-tweak-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Property, codeModelSchema, CodeModel, StringSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ChoiceSchema, Scheme, Schema } from '@azure-tools/codemodel';
import { Property, codeModelSchema, CodeModel, StringSchema, ObjectSchema, GroupSchema, isObjectSchema, SchemaType, GroupProperty, ParameterLocation, Operation, Parameter, VirtualParameter, getAllProperties, ImplementationLocation, OperationGroup, Request, SchemaContext, ChoiceSchema, Scheme, Schema, ConstantSchema } from '@azure-tools/codemodel';
//import { ModelState } from '@azure-tools/codemodel-v3';
//import { KnownMediaType, knownMediaType, ParameterLocation, getPolymorphicBases, isSchemaObject, JsonType, Property, Schema, processCodeModel, StringFormat, codemodel, ModelState } from '@azure-tools/codemodel-v3';
import { pascalCase, deconstruct, fixLeadingNumber, serialize, KnownMediaType } from '@azure-tools/codegen';
Expand Down Expand Up @@ -99,7 +99,7 @@ async function tweakModelV2(state: State): Promise<PwshModel> {
for (const operation of values(group.operations)) {
for (const param of values(operation.parameters).where(each => each.protocol?.http?.in === ParameterLocation.Path)) {
const name = param.language.default.name;
const hasName = universalId.properties?.find((prop) => prop.language.default.name === name);
const hasName = universalId.properties?.find((prop) => prop.language.default.name.toLocaleLowerCase() === name.toLocaleLowerCase());
if (!hasName) {
if (!universalId.properties) {
universalId.properties = [];
Expand Down Expand Up @@ -277,10 +277,15 @@ async function tweakModelV2(state: State): Promise<PwshModel> {
for (const group of values(model.operationGroups)) {
for (const operation of values(group.operations)) {
for (const parameter of values(operation.parameters)) {
if (parameter.required && parameter.schema instanceof ChoiceSchema) {
const choiceSchema = parameter.schema as ChoiceSchema;
if (choiceSchema.choices.length === 1) {
parameter.language.default.constantValue = choiceSchema.choices[0].value;
if (parameter.required) {
if (parameter.schema.type === SchemaType.Choice) {
const choiceSchema = parameter.schema as ChoiceSchema;
if (choiceSchema.choices.length === 1) {
parameter.language.default.constantValue = choiceSchema.choices[0].value;
}
} else if (parameter.schema.type === SchemaType.Constant) {
const constantSchema = parameter.schema as ConstantSchema;
parameter.language.default.constantValue = constantSchema.value.value;
}
}
}
Expand All @@ -290,12 +295,17 @@ async function tweakModelV2(state: State): Promise<PwshModel> {
// identify properties that are constants
for (const schema of values(schemas.objects)) {
for (const property of values(schema.properties)) {
if (property.required && property.schema instanceof ChoiceSchema) {
const choiceSchema = property.schema as ChoiceSchema;
if (choiceSchema.choices.length === 1) {
// properties with an enum single value are constants
// add the constant value
property.language.default.constantValue = choiceSchema.choices[0].value;
if (property.required) {
if (property.schema.type === SchemaType.Choice) {
const choiceSchema = property.schema as ChoiceSchema;
if (choiceSchema.choices.length === 1) {
// properties with an enum single value are constants
// add the constant value
property.language.default.constantValue = choiceSchema.choices[0].value;
}
} else if (property.schema.type === SchemaType.Constant) {
const constantSchema = property.schema as ConstantSchema;
property.language.default.constantValue = constantSchema.value.value;
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion tests-upgrade/Configuration.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"extension-ms-paramlocation",
"directive-aliasremoval",
"directive-cmdlet",
"directive-parameter"
"directive-parameter",
"datamodels-datatypes-file"
],
"BlackList": [
"basic-get-querystr",
Expand Down