Skip to content
This repository has been archived by the owner on Dec 15, 2023. It is now read-only.

Commit

Permalink
Merge pull request #51 from Azure/smart-flatten
Browse files Browse the repository at this point in the history
Smart flatten
  • Loading branch information
RodgeFu authored Apr 5, 2020
2 parents f6d7a9c + 00b3aef commit dc7b078
Show file tree
Hide file tree
Showing 9 changed files with 488 additions and 60 deletions.
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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

Expand All @@ -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:
Expand Down Expand Up @@ -100,6 +106,18 @@ cli:
# type: SchemaType
# prop: propertyName
# flatten: true
# # max properties allowed from flatten
# cli-flatten-payload-max-prop: 32
# # max complexity allowed from flatten
# # a required json argument counted as 1
# # an optional json argument counted as 0.5
# cli-flatten-payload-max-complexity: 1
# # max depth of flatten
# cli-flatten-payload-max-level: 5
# # max properties allowed from flatten of object in array to avoid json
# cli-flatten-payload-max-array-object-prop: 8
# # max properties allowed from flatten of sub-class to avoid json
# cli-flatten-payload-max-subclass-prop: 8
polymorphism:
# if true, polymorphism parameter with 'poly-resource' marked as true will be
# expanded into multiple operations for each subclasses
Expand All @@ -111,6 +129,7 @@ cli:
appliedTo:
- name
- alias
- cli-discriminator-value
singularize:
- operationGroup
- operation
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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": {
Expand Down
12 changes: 8 additions & 4 deletions src/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,10 @@ export class Helper {
return (isNullOrUndefined(v)) ? '' : NEW_LINE + tab(i) + NodeHelper.FLATTEN_FLAG + ': ' + v;
};

let generatePropertyReadonlyValue = (o: any, i: number) => {
return (o['readOnly'] === true) ? (NEW_LINE + tab(i) + 'readOnly: true') : '';
};

let generateDiscriminatorValueForSchema = (o: Schema, i: number) => {
if (o instanceof ObjectSchema) {
let v = NodeHelper.HasSubClass(o);
Expand All @@ -338,20 +342,20 @@ export class Helper {
`${tab()}all:${NEW_LINE}`.concat(codeModel.operationGroups.map(
v => `${tab(1)}- operationGroupName: ${generateCliValue(v, 2)}` +
`${NEW_LINE}${tab(2)}operations:${NEW_LINE}`.concat(
v.operations.map(vv =>
values(v.operations).selectMany(op => [op].concat(NodeHelper.getCliOperation(op, () => []))).select(vv =>
`${tab(2)}- operationName: ${generateCliValue(vv, 3)}` +
(isNullOrUndefined(NodeHelper.getPolyAsResourceParam(vv)) ? '' : `${NEW_LINE}${tab(3)}cli-poly-as-resource-subclass-param: ${NodeHelper.getCliKey(NodeHelper.getPolyAsResourceParam(vv), '<missing-clikey>')}`) +
(isNullOrUndefined(NodeHelper.getPolyAsResourceOriginalOperation(vv)) ? '' : `${NEW_LINE}${tab(3)}cli-poly-as-resource-original-operation: ${NodeHelper.getCliKey(NodeHelper.getPolyAsResourceOriginalOperation(vv), '<missing-clikey>')}`) +
`${NEW_LINE}${tab(3)}parameters:${NEW_LINE}`.concat(
vv.parameters.map(vvv => `${tab(3)}- parameterName: ${generateCliValue(vvv, 4)}${generatePropertyFlattenValue(vvv, 4)}${generateDiscriminatorValueForParam(vvv, 4)}${NEW_LINE}` +
vv.parameters.map(vvv => `${tab(3)}- parameterName: ${generateCliValue(vvv, 4)}${generatePropertyFlattenValue(vvv, 4)}${generatePropertyReadonlyValue(vvv, 4)}${generateDiscriminatorValueForParam(vvv, 4)}${NEW_LINE}` +
(isNullOrUndefined(NodeHelper.getPolyAsResourceBaseSchema(vvv)) ? '' : `${tab(4)}cli-poly-as-resource-base-schema: ${NodeHelper.getCliKey(NodeHelper.getPolyAsResourceBaseSchema(vvv), '<baseSchemaCliKeyMissing>')}${NEW_LINE}`) +
(isNullOrUndefined(NodeHelper.getPolyAsParamBaseSchema(vvv)) ? '' : `${tab(4)}cli-poly-as-param-base-schema: ${NodeHelper.getCliKey(NodeHelper.getPolyAsParamBaseSchema(vvv), '<baseSchemaCliKeyMissing>')}${NEW_LINE}`) +
(isNullOrUndefined(NodeHelper.getPolyAsParamOriginalParam(vvv)) ? '' : `${tab(4)}cli-poly-as-param-expanded: ${NodeHelper.getCliKey(NodeHelper.getPolyAsParamOriginalParam(vvv), '<oriParamCliKeyMissing>')}${NEW_LINE}`) +
(((!isNullOrUndefined(vvv.protocol?.http?.in)) && vvv.protocol.http.in === 'body')
? `${tab(4)}bodySchema: ${vvv.schema.language.default.name}${NEW_LINE}` : '')).join('')) +
vv.requests.map((req, index) =>
isNullOrUndefined(req.parameters) ? '' :
req.parameters.map((vvv) => `${tab(3)}- parameterName[${index}]: ${generateCliValue(vvv, 4)}${generatePropertyFlattenValue(vvv, 4)}${generateDiscriminatorValueForParam(vvv, 4)}${NEW_LINE}` +
req.parameters.map((vvv) => `${tab(3)}- parameterName[${index}]: ${generateCliValue(vvv, 4)}${generatePropertyFlattenValue(vvv, 4)}${generatePropertyReadonlyValue(vvv, 4)}${generateDiscriminatorValueForParam(vvv, 4)}${NEW_LINE}` +
(isNullOrUndefined(NodeHelper.getPolyAsResourceBaseSchema(vvv)) ? '' : `${tab(4)}cli-poly-as-resource-base-schema: ${NodeHelper.getCliKey(NodeHelper.getPolyAsResourceBaseSchema(vvv), '<baseSchemaCliKeyMissing>')}${NEW_LINE}`) +
(isNullOrUndefined(NodeHelper.getPolyAsParamBaseSchema(vvv)) ? '' : `${tab(4)}cli-poly-as-param-base-schema: ${NodeHelper.getCliKey(NodeHelper.getPolyAsParamBaseSchema(vvv), '<baseSchemaCliKeyMissing>')}${NEW_LINE}`) +
(isNullOrUndefined(NodeHelper.getPolyAsParamOriginalParam(vvv)) ? '' : `${tab(4)}cli-poly-as-param-expanded: ${NodeHelper.getCliKey(NodeHelper.getPolyAsParamOriginalParam(vvv), '<oriParamCliKeyMissing>')}${NEW_LINE}`) +
Expand All @@ -366,7 +370,7 @@ export class Helper {
`${tab(1)}all:${NEW_LINE}`.concat(codeModel.schemas.objects.map(
v => `${tab(2)}- schemaName: ${generateCliValue(v, 3)}` + generateDiscriminatorValueForSchema(v, 3) +
`${NEW_LINE}${tab(3)}properties:${NEW_LINE}`.concat(
isNullOrUndefined(v.properties) ? '' : v.properties.map(vv => `${tab(4)}- propertyName: ${generateCliValue(vv, 5)}${generatePropertyFlattenValue(vv, 5)} ${NEW_LINE}`)
isNullOrUndefined(v.properties) ? '' : v.properties.map(vv => `${tab(4)}- propertyName: ${generateCliValue(vv, 5)}${generatePropertyFlattenValue(vv, 5)}${generatePropertyReadonlyValue(vv, 5)} ${NEW_LINE}`)
.join('')))
.join(''));
s = s + `${tab()}choices:${NEW_LINE}` +
Expand Down
106 changes: 102 additions & 4 deletions src/nodeHelper.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { codeModelSchema, ChoiceSchema, ChoiceValue, Extensions, CodeModel, ObjectSchema, Operation, OperationGroup, Parameter, Property, SealedChoiceSchema, Schema, ConstantSchema, SchemaType } from "@azure-tools/codemodel";
import { isArray, isNull, isNullOrUndefined, isObject, isString, isUndefined } from "util";
import { CliConst, M4Node, M4NodeType, NamingType, CliCommonSchema } from "./schema";
import { ArraySchema, DictionarySchema, Extensions, ObjectSchema, Operation, Parameter, Property, Schema } from "@azure-tools/codemodel";
import { isNullOrUndefined, isUndefined } from "util";
import { CliCommonSchema, M4Node } from "./schema";
import { Helper } from "./helper";

export class NodeHelper {
private static readonly CLI: string = "cli";
Expand All @@ -10,10 +11,15 @@ export class NodeHelper {
private static readonly CLI_HIDDEN: string = "hidden";
private static readonly CLI_REMOVED: string = "removed";
private static readonly CLI_COMPLEXITY: string = "cli-complexity";
private static readonly CLI_SIMPLIFIER_INDICATOR: string = "cli-simplify-indicator";
private static readonly CLI_IN_CIRCLE: string = "cli-in-circle";
private static readonly CLI_MARK: string = "cli-mark";
private static readonly CLI_IS_VISIBLE: string = "cli-is-visible";
private static readonly CLI_OPERATIONS: string = "cli-operations";
private static readonly JSON: string = "json";
public static readonly FLATTEN_FLAG: string = 'x-ms-client-flatten';
public static readonly DISCRIMINATOR_FLAG: string = 'discriminator';
public static readonly CLI_DISCRIMINATOR_VALUE: string = 'cli-discriminator-value';
public static readonly POLY_RESOURCE: string = 'poly-resource';
private static readonly POLY_AS_RESOURCE_SUBCLASS_PARAM = "cli-poly-as-resource-subclass-param";
private static readonly POLY_AS_RESOURCE_BASE_SCHEMA = 'cli-poly-as-resource-base-schema';
Expand All @@ -32,6 +38,34 @@ export class NodeHelper {
return !isNullOrUndefined(node.discriminator);
}

public static *getSubClasses(baseSchema: ObjectSchema, leafOnly: boolean) {

let allSubs = baseSchema.discriminator?.all;
if (isNullOrUndefined(allSubs))
return [];

for (let key in allSubs) {
let subClass = allSubs[key];
if (!(subClass instanceof ObjectSchema)) {
Helper.logWarning("subclass is not ObjectSchema: " + subClass.language.default.name);
continue;
}
if (NodeHelper.HasSubClass(subClass) && leafOnly) {
Helper.logWarning("skip subclass which also has subclass: " + subClass.language.default.name);
continue;
}
yield subClass;
}
}

public static setCliDiscriminatorValue(node: ObjectSchema, value: string) {
return NodeHelper.setCliProperty(node, this.CLI_DISCRIMINATOR_VALUE, value);
}

public static getCliDiscriminatorValue(node: ObjectSchema) {
return NodeHelper.getCliProperty(node, this.CLI_DISCRIMINATOR_VALUE, () => node.discriminatorValue);
}

public static setJson(node: M4Node, isJson: boolean, modifyFlatten: boolean) {

if (modifyFlatten && isJson) {
Expand Down Expand Up @@ -102,6 +136,10 @@ export class NodeHelper {
return isNullOrUndefined(node?.language[NodeHelper.CLI]) ? defaultValue : node.language[NodeHelper.CLI][NodeHelper.NAME];
}

public static getDefaultNameWithType(node: ObjectSchema | DictionarySchema | ArraySchema) {
return `${node.language.default.name}(${node instanceof ObjectSchema ? node.type : node instanceof DictionarySchema ? (node.elementType.language.default.name + '^dictionary') : (node.elementType.language.default.name + '^array')})`;
}

public static setHidden(node: M4Node, value: boolean) {
NodeHelper.setCliProperty(node, NodeHelper.CLI_HIDDEN, value);
}
Expand Down Expand Up @@ -178,8 +216,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 {
Expand Down Expand Up @@ -210,6 +253,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))
Expand Down Expand Up @@ -247,4 +295,54 @@ export class NodeHelper {
}
return node.extensions[propertyName];
}

public static setSimplifyIndicator(schema: ObjectSchema, indicator: CliCommonSchema.CodeModel.SimplifyIndicator): CliCommonSchema.CodeModel.SimplifyIndicator {
this.setCliProperty(schema, this.CLI_SIMPLIFIER_INDICATOR, indicator);
return indicator;
}

public static getSimplifyIndicator(schema: ObjectSchema): CliCommonSchema.CodeModel.SimplifyIndicator {
return this.getCliProperty(schema, this.CLI_SIMPLIFIER_INDICATOR, () => undefined);
}

public static clearSimplifyIndicator(schema: ObjectSchema) {
return this.clearCliProperty(schema, this.CLI_SIMPLIFIER_INDICATOR);
}

public static setInCircle(schema: ObjectSchema | ArraySchema | DictionarySchema, inCircle: boolean): boolean {
this.setCliProperty(schema, this.CLI_IN_CIRCLE, inCircle);
return inCircle;
}

public static getInCircle(schema: ObjectSchema | ArraySchema | DictionarySchema): boolean {
return this.getCliProperty(schema, this.CLI_IN_CIRCLE, () => undefined);
}

public static clearInCircle(schema: ObjectSchema | ArraySchema | DictionarySchema) {
return this.clearCliProperty(schema, this.CLI_IN_CIRCLE);
}


public static setMark(node: M4Node, mark: string): string {
NodeHelper.setCliProperty(node, NodeHelper.CLI_MARK, mark);
return mark;
}

public static getMark(node: M4Node): string {
return NodeHelper.getCliProperty(node, NodeHelper.CLI_MARK, () => undefined);
}

public static clearMark(node: M4Node) {
NodeHelper.clearCliProperty(node, NodeHelper.CLI_MARK);
}

public static addCliOperation(originalOperation: Operation, cliOperation: Operation) {
let v: Operation[] = NodeHelper.getExtensionsProperty(originalOperation, this.CLI_OPERATIONS, () => []);
v.push(cliOperation);
NodeHelper.setExtensionsProperty(originalOperation, this.CLI_OPERATIONS, v);
}

public static getCliOperation(originalOperation: Operation, defaultValue: () => any): Operation[] {
return NodeHelper.getExtensionsProperty(originalOperation, this.CLI_OPERATIONS, defaultValue);
}
}
Loading

0 comments on commit dc7b078

Please sign in to comment.