Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean LG/Expression #1873

Merged
merged 5 commits into from
Mar 8, 2020
Merged
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
28 changes: 10 additions & 18 deletions libraries/adaptive-expressions/src/constant.ts
Original file line number Diff line number Diff line change
@@ -42,30 +42,22 @@ export class Constant extends Expression {
}

public toString(): string {

if (this.value === undefined) {
return 'null';
}

if (typeof this.value === 'string') {
if (this.value.includes('\\')) {
this.value = this.value.replace(/\\/g, '\\\\');
} else if (typeof this.value === 'string') {
let result = this.value;
if (result.includes('\\')) {
result = result.replace(/\\/g, '\\\\');
}

return this.value.includes(`'`) ? `"${ this.value }"` : `'${ this.value }'`;
}

if (typeof this.value === 'number') {
return result.includes(`'`) ? `"${ result }"` : `'${ result }'`;
} else if (typeof this.value === 'number') {
return this.value.toString();
} else if(typeof this.value === 'object') {
return JSON.stringify(this.value);
}

if (Array.isArray(this.value)) {
this.value = '[' + this.value.join(' ') + ']';
}

if(typeof this.value === 'object') {
this.value = JSON.stringify(this.value);
}

return this.value === undefined ? undefined : this.value.toString();
return this.value.toString();
}
}
17 changes: 5 additions & 12 deletions libraries/adaptive-expressions/src/expression.ts
Original file line number Diff line number Diff line change
@@ -13,14 +13,6 @@ import { SimpleObjectMemory, MemoryInterface } from './memory';
import { Extensions } from './extensions';
import { ExpressionParser } from './parser';

/**
* key value pair to add method in FunctionTable
*/
type keyValuePair = {
key: string;
value: ExpressionEvaluator;
}

/**
* Type expected from evalating an expression.
*/
@@ -121,7 +113,7 @@ export class Expression {

}

public add(item: keyValuePair | string, value: ExpressionEvaluator = undefined): void{
public add(item: {key: string; value: ExpressionEvaluator} | string, value: ExpressionEvaluator|undefined): void{
if(arguments.length === 1 && item instanceof Object) {
this.set(item.key, item.value);
} else if (arguments.length == 2 && typeof item === 'string') {
@@ -141,7 +133,8 @@ export class Expression {
return this.customFunctions.delete(key);
}

public forEach(callbackfn: (value: ExpressionEvaluator, key: string, map: Map<string, ExpressionEvaluator>) => void, thisArg?: any): void {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public forEach(_callbackfn: (value: ExpressionEvaluator, key: string, map: Map<string, ExpressionEvaluator>) => void, thisArg?: any): void {
throw Error(`forEach function not implemented`);
}

@@ -184,8 +177,8 @@ export class Expression {
}
}

public static parse(expression: string, lookup: EvaluatorLookup): Expression {
return new ExpressionParser(lookup? lookup : Expression.lookup).parse(expression);
public static parse(expression: string, lookup?: EvaluatorLookup): Expression {
return new ExpressionParser(lookup || Expression.lookup).parse(expression);
}

/**
4 changes: 1 addition & 3 deletions libraries/adaptive-expressions/src/expressionEvaluator.ts
Original file line number Diff line number Diff line change
@@ -56,9 +56,8 @@ export class ExpressionEvaluator {
this.type = type;
this._evaluator = evaluator;
this.returnType = returnType;
// tslint:disable-next-line: no-empty
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this._validator = validator === undefined ? ((expr: Expression): any => { }) : validator;
this._validator = validator || ((expr: Expression): any => { });
}

/**
@@ -71,6 +70,5 @@ export class ExpressionEvaluator {
* Validate an expression.
* @param expression Expression to validate.
*/
// tslint:disable-next-line: informative-docs
public validateExpression = (expression: Expression): void => this._validator(expression);
}
37 changes: 11 additions & 26 deletions libraries/adaptive-expressions/src/expressionFunctions.ts
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ import { EvaluateExpressionDelegate, ExpressionEvaluator, ValidateExpressionDele
import { ExpressionType } from './expressionType';
import { Extensions } from './extensions';
import { TimeZoneConverter } from './timeZoneConverter';
import { convertCSharpDateTimeToMomentJS } from './formatConverter';
import { convertCSharpDateTimeToMomentJS } from './datetimeFormatConverter';
import { MemoryInterface, SimpleObjectMemory, StackedMemory } from './memory';

/**
@@ -531,7 +531,6 @@ export class ExpressionFunctions {
(args: any []): any => {
const binaryArgs: any[] = [undefined, undefined];
let soFar: any = args[0];
// tslint:disable-next-line: prefer-for-of
for (let i = 1; i < args.length; i++) {
binaryArgs[0] = soFar;
binaryArgs[1] = args[i];
@@ -557,7 +556,6 @@ export class ExpressionFunctions {
let soFar: any = args[0];
let value: any;
let error: string;
// tslint:disable-next-line: prefer-for-of
for (let i = 1; i < args.length; i++) {
binaryArgs[0] = soFar;
binaryArgs[1] = args[i];
@@ -602,7 +600,7 @@ export class ExpressionFunctions {
* @param func Function to apply.
*/
public static multivariateNumeric(type: string, func: (arg0: any []) => any, verify?: VerifyExpression): ExpressionEvaluator {
return new ExpressionEvaluator(type, ExpressionFunctions.applySequence(func, verify !== undefined ? verify : ExpressionFunctions.verifyNumber),
return new ExpressionEvaluator(type, ExpressionFunctions.applySequence(func, verify || ExpressionFunctions.verifyNumber),
ReturnType.Number, ExpressionFunctions.validateTwoOrMoreThanTwoNumbers);
}
/**
@@ -692,7 +690,6 @@ export class ExpressionFunctions {
return { value: result, error };
},
ReturnType.String,
// tslint:disable-next-line: no-void-expression
(expr: Expression): void => ExpressionFunctions.validateArityAndAnyType(expr, 2, 3, ReturnType.String, ReturnType.Number));
}

@@ -770,7 +767,6 @@ export class ExpressionFunctions {
private static newGuid(): string {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c: any): string => {
const r: number = Math.random() * 16 | 0;
// tslint:disable-next-line: no-bitwise
const v: number = c === 'x' ? r : (r & 0x3 | 0x8);

return v.toString(16);
@@ -1006,13 +1002,12 @@ export class ExpressionFunctions {
}

if (!error) {
// 2nd parameter has been rewrite to $local.item
const iteratorName = (expression.children[1].children[0] as Constant).value as string;
let arr = [];
if (Array.isArray(instance)) {
arr = instance;
} else if (typeof instance === 'object') {
Object.keys(instance).forEach(u => arr.push({key: u, value: instance[u]}));
Object.keys(instance).forEach((u): number => arr.push({key: u, value: instance[u]}));
} else {
error = `${ expression.children[0] } is not a collection or structure object to run foreach`;
}
@@ -1054,7 +1049,7 @@ export class ExpressionFunctions {
arr = instance;
isInstanceArray = true;
} else if (typeof instance === 'object') {
Object.keys(instance).forEach(u => arr.push({key: u, value: instance[u]}));
Object.keys(instance).forEach((u): number => arr.push({key: u, value: instance[u]}));
} else {
error = `${ expression.children[0] } is not a collection or structure object to run foreach`;
}
@@ -1116,8 +1111,7 @@ export class ExpressionFunctions {

const second: Expression = expression.children[1];
if (second.returnType === ReturnType.String && second.type === ExpressionType.Constant) {
// tslint:disable-next-line: restrict-plus-operands
CommonRegex.CreateRegex((second as Constant).value + '');
CommonRegex.CreateRegex((second as Constant).value.toString());
}
}

@@ -1389,7 +1383,7 @@ export class ExpressionFunctions {
({value: propertyName, error} = expression.children[1].tryEvaluate(state));

if (!error) {
propertyName = propertyName === undefined ? '' : propertyName;
propertyName = propertyName || '';
}
if (isDescending) {
result = lodash.sortBy(arr, propertyName).reverse();
@@ -1439,7 +1433,6 @@ export class ExpressionFunctions {
let result = '';
for (const element of stringToConvert) {
const binaryElement: string = element.charCodeAt(0).toString(2);
// tslint:disable-next-line: prefer-array-literal
result += new Array(9 - binaryElement.length).join('0').concat(binaryElement);
}

@@ -1784,9 +1777,8 @@ export class ExpressionFunctions {
}

private static flatten(arr: any[], dept: number): any[]{
dept = typeof dept === 'undefined' ? 1 : dept;
if (typeof dept !== 'number') {
return;
if (!ExpressionFunctions.isNumber(dept) || dept < 1) {
dept = 1;
}

let res = JSON.parse(JSON.stringify(arr));
@@ -1802,11 +1794,7 @@ export class ExpressionFunctions {
return res;
}



// tslint:disable-next-line: max-func-body-length
private static getStandardFunctions(): ReadonlyMap<string, ExpressionEvaluator> {
// tslint:disable-next-line: no-unnecessary-local-variable
const functions: ExpressionEvaluator[] = [
//Math
new ExpressionEvaluator(ExpressionType.Element, ExpressionFunctions.extractElement, ReturnType.Object, this.validateBinary),
@@ -1961,7 +1949,6 @@ export class ExpressionFunctions {
error = 'Second paramter must be more than zero';
}

// tslint:disable-next-line: prefer-array-literal
const result: number[] = [...Array(args[1]).keys()].map((u: number): number => u + Number(args[0]));

return { value: result, error };
@@ -2034,7 +2021,7 @@ export class ExpressionFunctions {
new ExpressionEvaluator(
ExpressionType.Flatten,
ExpressionFunctions.apply(
args => {
(args: any []): any[] => {
let array = args[0];
let depth = args.length > 1 ? args[1] : 100;
return ExpressionFunctions.flatten(array, depth);
@@ -2044,7 +2031,7 @@ export class ExpressionFunctions {
),
new ExpressionEvaluator(
ExpressionType.Unique,
ExpressionFunctions.apply(args => [... new Set(args[0])]),
ExpressionFunctions.apply((args: any []): any[] => [... new Set(args[0])]),
ReturnType.Object,
(expression: Expression): void => ExpressionFunctions.validateOrder(expression, [], ReturnType.Object)
),
@@ -2175,7 +2162,7 @@ export class ExpressionFunctions {
(expression: Expression): void => ExpressionFunctions.validateArityAndAnyType(expression, 3, 3, ReturnType.String)),
new ExpressionEvaluator(
ExpressionType.Split,
ExpressionFunctions.apply((args: any []): string[] => ExpressionFunctions.parseStringOrNull(args[0]).split(ExpressionFunctions.parseStringOrNull(args[1]? args[1]: '')), ExpressionFunctions.verifyStringOrNull),
ExpressionFunctions.apply((args: any []): string[] => ExpressionFunctions.parseStringOrNull(args[0]).split(ExpressionFunctions.parseStringOrNull(args[1] || '')), ExpressionFunctions.verifyStringOrNull),
ReturnType.Object,
(expression: Expression): void => ExpressionFunctions.validateArityAndAnyType(expression, 1, 2, ReturnType.String)),
new ExpressionEvaluator(
@@ -2823,7 +2810,6 @@ export class ExpressionFunctions {
error = `Min value ${ args[0] } cannot be greater than max value ${ args[1] }.`;
}

// tslint:disable-next-line: insecure-random
const value: any = Math.floor(Math.random() * (Number(args[1]) - Number(args[0])) + Number(args[0]));

return { value, error };
@@ -2855,7 +2841,6 @@ export class ExpressionFunctions {
ExpressionFunctions.validateUnary),
new ExpressionEvaluator(
ExpressionType.DataUriToString,
// tslint:disable-next-line: restrict-plus-operands
ExpressionFunctions.apply((args: Readonly<any>): string => Buffer.from(args[0].slice(args[0].indexOf(',') + 1), 'base64').toString(), ExpressionFunctions.verifyString),
ReturnType.String,
ExpressionFunctions.validateUnary),
4 changes: 1 addition & 3 deletions libraries/adaptive-expressions/src/expressionType.ts
Original file line number Diff line number Diff line change
@@ -100,8 +100,6 @@ export class ExpressionType {
public static readonly Base64ToBinary: string = 'base64ToBinary';
public static readonly Base64ToString: string = 'base64ToString';
public static readonly UriComponent: string = 'uriComponent';
// TODO
// xml

// Memory
public static readonly Accessor: string = 'Accessor';
@@ -144,7 +142,7 @@ export class ExpressionType {

// TODO
// xPath
// jPath
// xml

// URI parsing functions
public static readonly UriHost: string = 'uriHost';
9 changes: 4 additions & 5 deletions libraries/adaptive-expressions/src/extensions.ts
Original file line number Diff line number Diff line change
@@ -55,7 +55,7 @@ export class Extensions {
* @returns Accessor path of expression.
*/
public static referenceWalk(expression: Expression,
extension?: (arg0: Expression) => boolean): {path:string; refs:Set<string>} {
extension?: (arg0: Expression) => boolean): {path: string; refs: Set<string>} {
let path: string;
let refs = new Set<string>();
if (extension === undefined || !extension(expression)) {
@@ -114,23 +114,23 @@ export class Extensions {
}

const iteratorName = (children[1].children[0] as Constant).value as string;
var nonLocalRefs2 = Array.from(refs2).filter(x => !(x === iteratorName || x.startsWith(iteratorName + '.') || x.startsWith(iteratorName + '[')));
var nonLocalRefs2 = Array.from(refs2).filter((x): boolean => !(x === iteratorName || x.startsWith(iteratorName + '.') || x.startsWith(iteratorName + '[')));
refs = new Set([...refs, ...refs0, ...nonLocalRefs2]);

} else {
for (const child of expression.children) {
const result = Extensions.referenceWalk(child, extension);
const childPath = result.path;
const refs0 = result.refs;
refs = new Set([...refs, ...refs0])
refs = new Set([...refs, ...refs0]);
if (childPath !== undefined) {
refs.add(childPath);
}
}
}
}

return {path, refs}
return {path, refs};
}

/**
@@ -146,7 +146,6 @@ export class Extensions {
}

let value: any;
// tslint:disable-next-line: prefer-const
let error: string;
// todo, Is there a better way to access value, or any case is not listed below?
if (instance instanceof Map && instance as Map<string, any>!== undefined) {
2 changes: 1 addition & 1 deletion libraries/adaptive-expressions/src/index.ts
Original file line number Diff line number Diff line change
@@ -19,4 +19,4 @@ export * from './parser';
export * from './memory';
export * from './regexErrorListener';
export * from './componentExpressionFunctions';
export * from './formatConverter';
export * from './datetimeFormatConverter';
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { MemoryInterface } from './memoryInterface';
import { Extensions } from '../extensions';
import { Util } from '../parser/util';

/**
* @module adaptive-expressions
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

/**
* @module adaptive-expressions
*/
@@ -7,9 +6,7 @@
* Licensed under the MIT License.
*/
import { ANTLRInputStream, CommonTokenStream } from 'antlr4ts';
// tslint:disable-next-line: no-submodule-imports
import { AbstractParseTreeVisitor, ParseTree, TerminalNode } from 'antlr4ts/tree';
import { ExpressionFunctions } from '../expressionFunctions';
import { Constant } from '../constant';
import { Expression } from '../expression';
import { EvaluatorLookup } from '../expressionEvaluator';
@@ -29,7 +26,6 @@ export class ExpressionParser implements ExpressionParserInterface {
*/
public readonly EvaluatorLookup: EvaluatorLookup;

// tslint:disable-next-line: typedef
private readonly ExpressionTransformer = class extends AbstractParseTreeVisitor<Expression> implements ExpressionAntlrParserVisitor<Expression> {

private readonly _lookupFunction: EvaluatorLookup = undefined;
@@ -209,7 +205,7 @@ export class ExpressionParser implements ExpressionParserInterface {
};

public constructor(lookup?: EvaluatorLookup) {
this.EvaluatorLookup = lookup === undefined ? Expression.lookup : lookup;
this.EvaluatorLookup = lookup || Expression.lookup;
}

protected static antlrParse(expression: string): ParseTree {
Loading