This commit is contained in:
Rodge Fu 2020-04-01 23:52:36 +08:00
Родитель f6d7a9c244
Коммит ad23f4eed3
6 изменённых файлов: 193 добавлений и 24 удалений

Просмотреть файл

@ -17,8 +17,12 @@ pipeline:
input: modelerfour
output-artifact: clicommon-prenamer
clicommon/cli-flatten-setter:
clicommon/pre/cli-complex-marker:
input: clicommon/cli-prenamer
output-artifact: clicommon-complex-marker-pre
clicommon/cli-flatten-setter:
input: clicommon/pre/cli-complex-marker
output-artifact: clicommon-flatten-setter
clicommon:
@ -52,6 +56,7 @@ pipeline:
#- clicommon/cli-poly-as-param-modifier
- clicommon/cli-poly-as-resource-modifier
- clicommon/cli-complex-marker
- clicommon/pre/cli-complex-marker
- clicommon/cli-visibility-cleaner
scope: scope-clicommon
@ -64,6 +69,7 @@ scope-clicommon:
- clicommon-poly-as-resource-modifier
#- clicommon-poly-as-param-modifier
- clicommon-complex-marker
- clicommon-complex-marker-pre
- clicommon-visibility-cleaner
modelerfour:

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "@autorest/clicommon",
"version": "0.4.2",
"version": "0.4.3",
"description": "Autorest Azure Cli Common Module",
"main": "dist/index.js",
"engines": {

Просмотреть файл

@ -178,8 +178,13 @@ export class NodeHelper {
return NodeHelper.getCliProperty(param, NodeHelper.POLY_AS_PARAM_EXPANDED, () => false);
}
public static setComplex(node: M4Node, complexity: CliCommonSchema.CodeModel.Complexity) {
public static setComplex(node: M4Node, complexity: CliCommonSchema.CodeModel.Complexity): CliCommonSchema.CodeModel.Complexity {
NodeHelper.setCliProperty(node, NodeHelper.CLI_COMPLEXITY, complexity);
return complexity;
}
public static clearComplex(node: M4Node) {
NodeHelper.clearCliProperty(node, NodeHelper.CLI_COMPLEXITY);
}
public static getComplexity(node: M4Node): CliCommonSchema.CodeModel.Complexity {
@ -210,6 +215,11 @@ export class NodeHelper {
node.language[NodeHelper.CLI][key] = value;
}
public static clearCliProperty(node: M4Node, key: string): void {
if (!isNullOrUndefined(node.language[NodeHelper.CLI]) && !isUndefined(node.language[NodeHelper.CLI][key]))
delete node.language[NodeHelper.CLI][key];
}
public static getCliProperty(node: M4Node, propertyName: string, defaultWhenNotExist: () => any): any {
if (isNullOrUndefined(node.language[NodeHelper.CLI])) {
if (isNullOrUndefined(defaultWhenNotExist))

Просмотреть файл

@ -79,11 +79,9 @@ class ComplexMarker {
if (obj.properties && obj.properties.length > 0) {
for (let prop of obj.properties) {
if (isObjectSchema(prop.schema)) {
let c = this.calculateObject(prop.schema);
if (c == CliCommonSchema.CodeModel.Complexity.object_complex) {
NodeHelper.setComplex(obj, CliCommonSchema.CodeModel.Complexity.object_complex);
return CliCommonSchema.CodeModel.Complexity.object_complex;
}
this.calculateObject(prop.schema);
NodeHelper.setComplex(obj, CliCommonSchema.CodeModel.Complexity.object_complex);
return CliCommonSchema.CodeModel.Complexity.object_complex;
}
else if (prop.schema instanceof ArraySchema) {
let c = this.calculateArray(prop.schema);
@ -104,8 +102,24 @@ class ComplexMarker {
}
private clearComplexMarker() {
}
public process() {
this.session.model.schemas.objects.forEach(obj => {
NodeHelper.clearComplex(obj);
});
this.session.model.schemas.dictionaries?.forEach(dict => {
NodeHelper.clearComplex(dict);
});
this.session.model.schemas.arrays?.forEach(arr => {
NodeHelper.clearComplex(arr);
})
this.session.model.schemas.objects.forEach(obj => {
this.calculateObject(obj);
});

Просмотреть файл

@ -1,6 +1,6 @@
import { Host, Session, startSession } from "@azure-tools/autorest-extension-base";
import { serialize } from "@azure-tools/codegen";
import { CodeModel, codeModelSchema, Metadata, ObjectSchema, isObjectSchema, Property, Extensions } from "@azure-tools/codemodel";
import { CodeModel, codeModelSchema, Metadata, ObjectSchema, isObjectSchema, Property, Extensions, getAllProperties, Parameter, DictionarySchema, Schema, ArraySchema, ConstantSchema, AnySchema } from "@azure-tools/codemodel";
import { isNullOrUndefined, isArray } from "util";
import { DESTRUCTION } from "dns";
import { Helper } from "../../helper";
@ -9,7 +9,12 @@ import { CliConst, CliCommonSchema } from "../../schema";
import { CliDirectiveManager } from "../modifier/cliDirective";
import { Modifier } from "../modifier/modifier";
import { FlattenValidator } from "./flattenValidator";
import { values } from "@azure-tools/linq";
import { values, Dictionary } from "@azure-tools/linq";
import { Z_DEFLATED } from "zlib";
class flattenInfo {
public constructor(public propCount: number = 0, public complexity: number = 0) { }
};
export class FlattenSetter {
codeModel: CodeModel;
@ -20,6 +25,126 @@ export class FlattenSetter {
this.codeModel = session.model;
}
/**
* level N means this is the Nth flatten, 0 means no flatten done which means the top level
* @param schema
* @param info - should be pre-prepared
* @param level
*/
private calcSchemaForPayloadFlatten(schema: Schema, info: flattenInfo[], level: number, required: boolean): number {
let weight = required ? 1 : 0.5;
let increasePropCount = () => {
for (let i = level; i < info.length; i++)
info[i].propCount++;
};
let increaseComplexity = () => {
for (let i = level; i < info.length; i++)
info[i].complexity = +weight;
};
let r = level;
if (schema instanceof ArraySchema) {
increasePropCount();
if (NodeHelper.getComplexity(schema) === CliCommonSchema.CodeModel.Complexity.array_complex)
increaseComplexity();
}
else if (schema instanceof DictionarySchema) {
increasePropCount();
if (NodeHelper.getComplexity(schema) === CliCommonSchema.CodeModel.Complexity.dictionary_complex)
increaseComplexity();
}
else if (schema instanceof AnySchema) {
increasePropCount();
increaseComplexity();
}
else if (schema instanceof ConstantSchema) {
}
else if (schema instanceof ObjectSchema) {
if (NodeHelper.HasSubClass(schema)) {
increasePropCount();
increaseComplexity();
}
else if (NodeHelper.getComplexity(schema) === CliCommonSchema.CodeModel.Complexity.object_simple) {
increasePropCount();
}
else {
info[level].propCount++;
info[level].complexity += weight;
for (let prop of getAllProperties(schema)) {
if (prop.readOnly)
continue;
if (level + 1 < info.length) {
r = this.calcSchemaForPayloadFlatten(prop.schema, info, level + 1, prop.required);
}
}
}
}
else {
increasePropCount();
}
return r;
}
private calcPayloadFlatten(param: Parameter, maxLevel: number, maxPropCount: number, maxComplexity: number): number {
let defaultLevel = 1;
let info: flattenInfo[] = [];
for (let i = maxLevel; i >= 0; i--)
info.push(new flattenInfo());
let r = this.calcSchemaForPayloadFlatten(param.schema, info, 0, true);
for (let i = 0; i <= r; i++) {
Helper.logDebug(`Level-${i}: propCount=${info[i].propCount}, complexity=${info[i].complexity}`)
}
for (let i = r; i >= 0; i--) {
if (info[i].propCount <= maxPropCount && info[i].complexity <= maxComplexity) {
if (i == 0 && NodeHelper.getComplexity(param.schema) === CliCommonSchema.CodeModel.Complexity.object_simple) {
Helper.logDebug(`flatten to level ${i} and ajusted to 1 for top level simple object with maxLevel=${maxLevel}, maxPropCount=${maxPropCount}, maxComplexity=${maxComplexity}`);
return 1;
}
else {
Helper.logDebug(`flatten to level ${i} with maxLevel=${maxLevel}, maxPropCount=${maxPropCount}, maxComplexity=${maxComplexity}`);
return i;
}
}
}
return defaultLevel;
}
private flattenSchemaFromPayload(schema: Schema, curLevel: number, maxLevel: number, overwritten: boolean) {
if (curLevel >= maxLevel)
return;
if (!(schema instanceof ObjectSchema))
return;
for (let prop of getAllProperties(schema)) {
if (prop.readOnly)
continue;
if (prop.schema instanceof ObjectSchema) {
if (!NodeHelper.HasSubClass(prop.schema) && NodeHelper.getComplexity(prop.schema) !== CliCommonSchema.CodeModel.Complexity.object_simple)
NodeHelper.setFlatten(prop, true, overwritten);
}
this.flattenSchemaFromPayload(prop.schema, curLevel + 1, maxLevel, overwritten);
}
}
private flattenPayload(param: Parameter, maxLevel: number, maxPropCount: number, maxComplexity: number, overwritten: boolean) {
let r = this.calcPayloadFlatten(param, maxLevel, maxPropCount, maxComplexity);
if (r > 0) {
NodeHelper.setFlatten(param, true, overwritten);
this.flattenSchemaFromPayload(param.schema, 1, r, overwritten);
}
}
async process(host: Host) {
let overwriteSwagger = await this.session.getValue(CliConst.CLI_FLATTEN_SET_FLATTEN_ALL_OVERWRITE_SWAGGER_KEY, false);
@ -31,32 +156,43 @@ export class FlattenSetter {
if (flattenSchema === true || flattenAll === true) {
this.codeModel.schemas.objects.forEach(o => {
if (!NodeHelper.HasSubClass(o)) {
if (!isNullOrUndefined(o.properties)) {
o.properties.forEach(p => {
if (isObjectSchema(p.schema)) {
NodeHelper.setFlatten(p, !NodeHelper.HasSubClass(p.schema as ObjectSchema), overwriteSwagger);
}
})
for (let p of getAllProperties(o)) {
if (isObjectSchema(p.schema)) {
NodeHelper.setFlatten(p, !NodeHelper.HasSubClass(p.schema as ObjectSchema), overwriteSwagger);
}
}
}
});
}
let maxPropCount = await this.session.getValue(CliConst.CLI_FLATTEN_SET_FLATTEN_PAYLOAD_MAX_PROP_KEY, 32);
let maxLevel = await this.session.getValue(CliConst.CLI_FLATTEN_SET_FLATTEN_PAYLOAD_MAX_LEVEL_KEY, 5);
let maxComplexity = await this.session.getValue(CliConst.CLI_FLATTEN_SET_FLATTEN_PAYLOAD_MAX_COMPLEXITY_KEY, 1);
let flattenPayload = await this.session.getValue(CliConst.CLI_FLATTEN_SET_FLATTEN_PAYLOAD_KEY, false);
if (flattenPayload === true || flattenAll === true) {
this.codeModel.operationGroups.forEach(group => {
group.operations.forEach(operation => {
values(operation.parameters)
values(operation.parameters)
.where(p => p.protocol.http?.in === 'body' && p.implementation === 'Method')
.forEach(p => NodeHelper.setFlatten(p, !NodeHelper.HasSubClass(p.schema as ObjectSchema), overwriteSwagger));
.forEach(p => {
if (p.schema instanceof ObjectSchema && !NodeHelper.HasSubClass(p.schema)) {
Helper.logDebug(`Try to set flatten for ${group.language.default.name}/${operation.language.default.name}/${p.language.default.name}`);
this.flattenPayload(p, maxLevel, maxPropCount, maxComplexity, overwriteSwagger);
}
});
operation.requests.forEach(request => {
if (!isNullOrUndefined(request.parameters)) {
values(request.parameters)
operation.requests.forEach(request => {
if (!isNullOrUndefined(request.parameters)) {
values(request.parameters)
.where(p => p.protocol.http?.in === 'body' && p.implementation === 'Method')
.forEach(p => NodeHelper.setFlatten(p, !NodeHelper.HasSubClass(p.schema as ObjectSchema), overwriteSwagger));
}
});
.forEach(p => {
if (p.schema instanceof ObjectSchema && !NodeHelper.HasSubClass(p.schema))
Helper.logDebug(`Try to set flatten for ${group.language.default.name}/${operation.language.default.name}/${p.language.default.name}`);
this.flattenPayload(p, maxLevel, maxPropCount, maxComplexity, overwriteSwagger);
});
}
});
})
})

Просмотреть файл

@ -18,6 +18,9 @@ export namespace CliConst {
export const CLI_FLATTEN_SET_FLATTEN_ALL_KEY: string = 'cli.flatten.cli-flatten-all';
export const CLI_FLATTEN_SET_FLATTEN_SCHEMA_KEY: string = 'cli.flatten.cli-flatten-schema';
export const CLI_FLATTEN_SET_FLATTEN_PAYLOAD_KEY: string = 'cli.flatten.cli-flatten-payload';
export const CLI_FLATTEN_SET_FLATTEN_PAYLOAD_MAX_PROP_KEY: string = 'cli.flatten.cli-flatten-payload-max-prop';
export const CLI_FLATTEN_SET_FLATTEN_PAYLOAD_MAX_COMPLEXITY_KEY: string = 'cli.flatten.cli-flatten-payload-max-complexity';
export const CLI_FLATTEN_SET_FLATTEN_PAYLOAD_MAX_LEVEL_KEY: string = 'cli.flatten.cli-flatten-payload-max-level';
export const CLI_FLATTEN_SET_FLATTEN_ALL_OVERWRITE_SWAGGER_KEY: string = 'cli.flatten.cli-flatten-all-overwrite-swagger';
export const DEFAULT_OPERATION_PARAMETER_INDEX = -1;