From 7feb45666975969ade7d11a6eb495ed950e1bf3d Mon Sep 17 00:00:00 2001 From: Cecilia Avila <44245136+ceciliaavila@users.noreply.github.com> Date: Wed, 27 Nov 2024 10:42:25 -0300 Subject: [PATCH 1/4] Add missing directory to workspaces (#4801) --- generators/generator-botbuilder/package.json | 2 +- package.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/generators/generator-botbuilder/package.json b/generators/generator-botbuilder/package.json index 43ca9fe063..2f98f73c56 100644 --- a/generators/generator-botbuilder/package.json +++ b/generators/generator-botbuilder/package.json @@ -1,6 +1,6 @@ { "name": "generator-botbuilder", - "version": "4.11.0", + "version": "4.1.6", "description": "A yeoman generator for creating bots built with Bot Framework v4", "homepage": "https://github.com/Microsoft/BotBuilder-JS/tree/main/generators/generator-botbuilder", "author": { diff --git a/package.json b/package.json index 8748f779d4..4ad0f3de24 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "tools" ], "generators": [ + "generators/generator-botbuilder", "generators/generator-botbuilder/generators/app/templates/*" ], "nohoist": [ From 925a2c6de80307a5d1cb0b9e478a86837f7ba9b2 Mon Sep 17 00:00:00 2001 From: Cecilia Avila <44245136+ceciliaavila@users.noreply.github.com> Date: Tue, 3 Dec 2024 18:51:34 -0300 Subject: [PATCH 2/4] fix: [#4684] ESLint issues in botbuilder-azure-blobs (#4802) * Fix ESLint issues in botbuilder-azure-blobs * Remove eslint-plugin-only-warn dependency --- libraries/botbuilder-azure-blobs/eslint.config.cjs | 10 ---------- libraries/botbuilder-azure-blobs/package.json | 3 +-- .../botbuilder-azure-blobs/src/blobsStorage.ts | 10 +++++----- .../src/blobsTranscriptStore.ts | 14 +++++++------- .../tests/blobsStorage.test.js | 5 +++-- .../tests/blobsTranscriptStore.test.js | 6 +++--- 6 files changed, 19 insertions(+), 29 deletions(-) delete mode 100644 libraries/botbuilder-azure-blobs/eslint.config.cjs diff --git a/libraries/botbuilder-azure-blobs/eslint.config.cjs b/libraries/botbuilder-azure-blobs/eslint.config.cjs deleted file mode 100644 index 63647b52cc..0000000000 --- a/libraries/botbuilder-azure-blobs/eslint.config.cjs +++ /dev/null @@ -1,10 +0,0 @@ -const onlyWarn = require("eslint-plugin-only-warn"); -const sharedConfig = require("../../eslint.config.cjs") - -module.exports = [ - ...sharedConfig, - { - plugins: { - "only-warn": onlyWarn, - }, - }]; diff --git a/libraries/botbuilder-azure-blobs/package.json b/libraries/botbuilder-azure-blobs/package.json index 656322961d..0e34526d4b 100644 --- a/libraries/botbuilder-azure-blobs/package.json +++ b/libraries/botbuilder-azure-blobs/package.json @@ -30,7 +30,6 @@ "@azure/storage-blob": "^12.24.0", "botbuilder-core": "4.1.6", "botbuilder-stdlib": "4.1.6", - "eslint-plugin-only-warn": "^1.1.0", "p-map": "^4.0.0", "zod": "^3.23.8", "@azure/core-http": "^3.0.4" @@ -40,7 +39,7 @@ "build-docs": "typedoc --theme markdown --entryPoint botbuilder-azure-blobs --excludePrivate --includeDeclarations --ignoreCompilerErrors --module amd --out ..\\..\\doc\\botbuilder-azure-blobs .\\lib\\index.d.ts --hideGenerator --name \"Bot Builder SDK - Azure Blobs\" --readme none", "clean": "rimraf _ts3.4 lib tsconfig.tsbuildinfo", "depcheck": "depcheck --config ../../.depcheckrc", - "lint": "eslint .", + "lint": "eslint . --config ../../eslint.config.cjs", "postbuild": "downlevel-dts lib _ts3.4/lib --checksum", "test": "yarn build && nyc mocha --check-leaks tests", "test:compat": "api-extractor run --verbose" diff --git a/libraries/botbuilder-azure-blobs/src/blobsStorage.ts b/libraries/botbuilder-azure-blobs/src/blobsStorage.ts index 985cd035c8..8b6825d89c 100644 --- a/libraries/botbuilder-azure-blobs/src/blobsStorage.ts +++ b/libraries/botbuilder-azure-blobs/src/blobsStorage.ts @@ -54,7 +54,7 @@ export class BlobsStorage implements Storage { containerName: string, options?: BlobsStorageOptions, url = '', - credential?: StorageSharedKeyCredential | AnonymousCredential | TokenCredential + credential?: StorageSharedKeyCredential | AnonymousCredential | TokenCredential, ) { if (url != '' && credential != null) { z.object({ url: z.string() }).parse({ @@ -80,7 +80,7 @@ export class BlobsStorage implements Storage { this._containerClient = new ContainerClient( connectionString, containerName, - options?.storagePipelineOptions + options?.storagePipelineOptions, ); // At most one promise at a time to be friendly to local emulator users @@ -121,7 +121,7 @@ export class BlobsStorage implements Storage { const blob = await ignoreError( this._containerClient.getBlobClient(sanitizeBlobKey(key)).download(), - isStatusCodeError(404) + isStatusCodeError(404), ); if (!blob) { @@ -140,7 +140,7 @@ export class BlobsStorage implements Storage { }, { concurrency: this._concurrency, - } + }, ) ).reduce((acc, { key, value }) => (value ? { ...acc, [key]: value } : acc), {}); } @@ -196,7 +196,7 @@ export class BlobsStorage implements Storage { (key) => ignoreError(this._containerClient.deleteBlob(sanitizeBlobKey(key)), isStatusCodeError(404)), { concurrency: this._concurrency, - } + }, ); } } diff --git a/libraries/botbuilder-azure-blobs/src/blobsTranscriptStore.ts b/libraries/botbuilder-azure-blobs/src/blobsTranscriptStore.ts index 23f1919847..af31ec7e7c 100644 --- a/libraries/botbuilder-azure-blobs/src/blobsTranscriptStore.ts +++ b/libraries/botbuilder-azure-blobs/src/blobsTranscriptStore.ts @@ -44,7 +44,7 @@ function getBlobKey(activity: Activity, options?: BlobsTranscriptStoreOptions): return sanitizeBlobKey( [activity.channelId, activity.conversation.id, `${formatTicks(timestamp)}-${activity.id}.json`].join('/'), - options + options, ); } @@ -102,7 +102,7 @@ export class BlobsTranscriptStore implements TranscriptStore { containerName: string, options?: BlobsTranscriptStoreOptions, blobServiceUri = '', - tokenCredential?: StorageSharedKeyCredential | AnonymousCredential | TokenCredential + tokenCredential?: StorageSharedKeyCredential | AnonymousCredential | TokenCredential, ) { if (blobServiceUri != '' && tokenCredential != null) { z.object({ blobServiceUri: z.string() }).parse({ @@ -116,7 +116,7 @@ export class BlobsTranscriptStore implements TranscriptStore { this._containerClient = new ContainerClient( blobServiceUri, tokenCredential, - options?.storagePipelineOptions + options?.storagePipelineOptions, ); // At most one promise at a time to be friendly to local emulator users @@ -132,7 +132,7 @@ export class BlobsTranscriptStore implements TranscriptStore { this._containerClient = new ContainerClient( connectionString, containerName, - options?.storagePipelineOptions + options?.storagePipelineOptions, ); // At most one promise at a time to be friendly to local emulator users @@ -170,7 +170,7 @@ export class BlobsTranscriptStore implements TranscriptStore { channelId: string, conversationId: string, continuationToken?: string, - startDate?: Date + startDate?: Date, ): Promise> { z.object({ channelId: z.string(), conversationId: z.string() }).parse({ channelId, conversationId }); @@ -195,7 +195,7 @@ export class BlobsTranscriptStore implements TranscriptStore { const fromIdx = startDate != null ? blobItems.findIndex( - (blobItem) => blobItem?.properties?.createdOn && blobItem?.properties?.createdOn >= startDate + (blobItem) => blobItem?.properties?.createdOn && blobItem?.properties?.createdOn >= startDate, ) : 0; @@ -213,7 +213,7 @@ export class BlobsTranscriptStore implements TranscriptStore { const activity = (await StreamConsumers.json(readableStreamBody)) as any; return { ...activity, timestamp: new Date(activity.timestamp) } as Activity; }, - { concurrency: this._concurrency } + { concurrency: this._concurrency }, ); activities.forEach((activity) => { diff --git a/libraries/botbuilder-azure-blobs/tests/blobsStorage.test.js b/libraries/botbuilder-azure-blobs/tests/blobsStorage.test.js index 348a4e7ce4..1a7fcb4dd8 100644 --- a/libraries/botbuilder-azure-blobs/tests/blobsStorage.test.js +++ b/libraries/botbuilder-azure-blobs/tests/blobsStorage.test.js @@ -26,7 +26,7 @@ describe('BlobsStorage', function () { assert.throws(() => new BlobsStorage(null, null, null, [], {}), 'throws for missing url'); assert.throws( () => new BlobsStorage(null, null, null, 'url', {}), - ReferenceError('Invalid credential type.') + ReferenceError('Invalid credential type.'), ); }); @@ -40,7 +40,7 @@ describe('BlobsStorage', function () { null, null, 'https://test.blob.core.windows.net/blob', - new StorageSharedKeyCredential('accountName', 'accountKey') + new StorageSharedKeyCredential('accountName', 'accountKey'), ); }); }); @@ -102,6 +102,7 @@ describe('BlobsStorage', function () { } let sandbox; + beforeEach(function () { sandbox = sinon.createSandbox({}); }); diff --git a/libraries/botbuilder-azure-blobs/tests/blobsTranscriptStore.test.js b/libraries/botbuilder-azure-blobs/tests/blobsTranscriptStore.test.js index 0399ad5255..96dc2157d5 100644 --- a/libraries/botbuilder-azure-blobs/tests/blobsTranscriptStore.test.js +++ b/libraries/botbuilder-azure-blobs/tests/blobsTranscriptStore.test.js @@ -72,7 +72,7 @@ describe('BlobsTranscriptStore', function () { assert.throws(() => new BlobsTranscriptStore(null, null, null, [], {}), 'throws for missing url'); assert.throws( () => new BlobsTranscriptStore(null, null, null, 'url', {}), - ReferenceError('Invalid credential type.') + ReferenceError('Invalid credential type.'), ); }); @@ -110,7 +110,7 @@ describe('BlobsTranscriptStore', function () { channelId, conversationId, undefined, - rest[0].timestamp + rest[0].timestamp, ); assert.deepStrictEqual(result.items, rest); }); @@ -154,7 +154,7 @@ describe('BlobsTranscriptStore', function () { channelId, id, created, - })) + })), ); }); }); From 64a10b15524cf2bf185ed3e0cca44ac8c9c6f4c6 Mon Sep 17 00:00:00 2001 From: Cecilia Avila <44245136+ceciliaavila@users.noreply.github.com> Date: Mon, 9 Dec 2024 15:07:52 -0300 Subject: [PATCH 3/4] Fix eslint issues in botbuilder-lg (#4803) --- libraries/botbuilder-lg/eslint.config.cjs | 11 +- libraries/botbuilder-lg/package.json | 1 - libraries/botbuilder-lg/src/analyzer.ts | 8 +- .../botbuilder-lg/src/customizedMemory.ts | 1 - libraries/botbuilder-lg/src/diagnostic.ts | 2 +- libraries/botbuilder-lg/src/errorListener.ts | 7 +- .../botbuilder-lg/src/evaluationOptions.ts | 1 - libraries/botbuilder-lg/src/evaluator.ts | 315 ++++++++-------- libraries/botbuilder-lg/src/expander.ts | 343 +++++++++--------- libraries/botbuilder-lg/src/extractor.ts | 15 +- libraries/botbuilder-lg/src/index.ts | 1 - .../botbuilder-lg/src/multiLanguageLG.ts | 2 +- libraries/botbuilder-lg/src/staticChecker.ts | 69 ++-- .../botbuilder-lg/src/templateExtensions.ts | 3 +- libraries/botbuilder-lg/src/templates.ts | 26 +- .../botbuilder-lg/src/templatesParser.ts | 58 ++- libraries/botbuilder-lg/tests/lg.test.js | 52 ++- .../botbuilder-lg/tests/lgDiagnostic.test.js | 92 ++--- .../tests/multilanguageLG.test.js | 2 +- 19 files changed, 512 insertions(+), 497 deletions(-) diff --git a/libraries/botbuilder-lg/eslint.config.cjs b/libraries/botbuilder-lg/eslint.config.cjs index d355eccb1c..ab85c270af 100644 --- a/libraries/botbuilder-lg/eslint.config.cjs +++ b/libraries/botbuilder-lg/eslint.config.cjs @@ -1,13 +1,8 @@ -const onlyWarn = require("eslint-plugin-only-warn"); -const sharedConfig = require("../../eslint.config.cjs") +const sharedConfig = require('../../eslint.config.cjs'); module.exports = [ ...sharedConfig, { - ignores: ["**/generated/*"], + ignores: ['**/generated/*'], }, - { - plugins: { - "only-warn": onlyWarn, - }, - }]; +]; diff --git a/libraries/botbuilder-lg/package.json b/libraries/botbuilder-lg/package.json index ec2c204e22..aebc699762 100644 --- a/libraries/botbuilder-lg/package.json +++ b/libraries/botbuilder-lg/package.json @@ -21,7 +21,6 @@ "dependencies": { "adaptive-expressions": "4.1.6", "antlr4ts": "0.5.0-alpha.4", - "eslint-plugin-only-warn": "^1.1.0", "lodash": "^4.17.19", "uuid": "^10.0.0" }, diff --git a/libraries/botbuilder-lg/src/analyzer.ts b/libraries/botbuilder-lg/src/analyzer.ts index 46775a9c47..5ff8b7dc3f 100644 --- a/libraries/botbuilder-lg/src/analyzer.ts +++ b/libraries/botbuilder-lg/src/analyzer.ts @@ -1,4 +1,3 @@ -/* eslint-disable security/detect-object-injection */ /** * @module botbuilder-lg */ @@ -16,7 +15,7 @@ import { LGTemplateParserVisitor } from './generated/LGTemplateParserVisitor'; import { Template } from './template'; import { TemplateExtensions } from './templateExtensions'; import { Templates } from './templates'; -import keyBy = require('lodash/keyBy'); +import keyBy from 'lodash/keyBy'; import { IfConditionRuleContext, @@ -37,7 +36,8 @@ import { TemplateErrors } from './templateErrors'; */ export class Analyzer extends AbstractParseTreeVisitor - implements LGTemplateParserVisitor { + implements LGTemplateParserVisitor +{ /** * Templates. */ @@ -85,7 +85,7 @@ export class Analyzer throw new Error( `${TemplateErrors.loopDetected} ${this.evalutationTargetStack .reverse() - .map((e) => e.templateName)} => ${templateName}` + .map((e) => e.templateName)} => ${templateName}`, ); } } diff --git a/libraries/botbuilder-lg/src/customizedMemory.ts b/libraries/botbuilder-lg/src/customizedMemory.ts index 58430f14f5..d95ecfae58 100644 --- a/libraries/botbuilder-lg/src/customizedMemory.ts +++ b/libraries/botbuilder-lg/src/customizedMemory.ts @@ -63,7 +63,6 @@ export class CustomizedMemory implements MemoryInterface { * @param _path Memory path. * @param _value Value to set. */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars setValue(_path: string, _value: any): void { return; } diff --git a/libraries/botbuilder-lg/src/diagnostic.ts b/libraries/botbuilder-lg/src/diagnostic.ts index 0c2aa691c1..a8deb8a989 100644 --- a/libraries/botbuilder-lg/src/diagnostic.ts +++ b/libraries/botbuilder-lg/src/diagnostic.ts @@ -43,7 +43,7 @@ export class Diagnostic { message: string, severity: DiagnosticSeverity = DiagnosticSeverity.Error, source?: string, - code?: string + code?: string, ) { this.message = message; this.range = range; diff --git a/libraries/botbuilder-lg/src/errorListener.ts b/libraries/botbuilder-lg/src/errorListener.ts index 96c394b4ec..8a04e8dc18 100644 --- a/libraries/botbuilder-lg/src/errorListener.ts +++ b/libraries/botbuilder-lg/src/errorListener.ts @@ -48,22 +48,21 @@ export class ErrorListener implements ANTLRErrorListener { offendingSymbol: any, line: number, charPositionInLine: number, - // eslint-disable-next-line @typescript-eslint/no-unused-vars msg: string, // eslint-disable-next-line @typescript-eslint/no-unused-vars - e: RecognitionException | undefined + e: RecognitionException | undefined, ): void { const startPosition: Position = new Position(this.lineOffset + line, charPositionInLine); const stopPosition: Position = new Position( this.lineOffset + line, - charPositionInLine + offendingSymbol.stopIndex - offendingSymbol.startIndex + 1 + charPositionInLine + offendingSymbol.stopIndex - offendingSymbol.startIndex + 1, ); const range: Range = new Range(startPosition, stopPosition); const diagnostic: Diagnostic = new Diagnostic( range, TemplateErrors.syntaxError(msg), DiagnosticSeverity.Error, - this.source + this.source, ); throw new TemplateException(diagnostic.toString(), [diagnostic]); diff --git a/libraries/botbuilder-lg/src/evaluationOptions.ts b/libraries/botbuilder-lg/src/evaluationOptions.ts index a2cac51423..c73fd6ccfa 100644 --- a/libraries/botbuilder-lg/src/evaluationOptions.ts +++ b/libraries/botbuilder-lg/src/evaluationOptions.ts @@ -1,4 +1,3 @@ -/* eslint-disable security/detect-object-injection */ /** * @module botbuilder-lg */ diff --git a/libraries/botbuilder-lg/src/evaluator.ts b/libraries/botbuilder-lg/src/evaluator.ts index 2c1110a1d4..ec5c7a8129 100644 --- a/libraries/botbuilder-lg/src/evaluator.ts +++ b/libraries/botbuilder-lg/src/evaluator.ts @@ -1,4 +1,3 @@ -/* eslint-disable security/detect-object-injection */ /* eslint-disable security/detect-non-literal-fs-filename */ /** * @module botbuilder-lg @@ -19,7 +18,7 @@ import { Template } from './template'; import { TemplateErrors } from './templateErrors'; import { TemplateExtensions } from './templateExtensions'; import { Templates } from './templates'; -import keyBy = require('lodash/keyBy'); +import keyBy from 'lodash/keyBy'; import { Constant, @@ -118,7 +117,7 @@ export class Evaluator extends AbstractParseTreeVisitor implements LGTe // generate a new customzied expression parser by injecting the templates as functions this.expressionParser = new ExpressionParser( - this.customizedEvaluatorLookup(templates.expressionParser.EvaluatorLookup) + this.customizedEvaluatorLookup(templates.expressionParser.EvaluatorLookup), ); } @@ -145,7 +144,7 @@ export class Evaluator extends AbstractParseTreeVisitor implements LGTe `${TemplateErrors.loopDetected} ${this.evaluationTargetStack .reverse() .map((u: EvaluationTarget): string => u.templateName) - .join(' => ')}` + .join(' => ')}`, ); } @@ -184,7 +183,7 @@ export class Evaluator extends AbstractParseTreeVisitor implements LGTe if (this.evaluationTargetStack.length !== 0) { this.evaluationTargetStack[this.evaluationTargetStack.length - 1].cachedEvaluatedChildren.set( currentEvulateId, - result + result, ); } } @@ -216,7 +215,7 @@ export class Evaluator extends AbstractParseTreeVisitor implements LGTe const propertyObject = this.evalExpression( body.expressionInStructure().text, body.expressionInStructure(), - body.text + body.text, ); // Full reference to another structured template is limited to the structured template with same type if ( @@ -247,7 +246,7 @@ export class Evaluator extends AbstractParseTreeVisitor implements LGTe for (const item of values) { if (TemplateExtensions.isPureExpression(item)) { result.push( - this.evalExpression(item.expressionInStructure(0).text, item.expressionInStructure(0), ctx.text) + this.evalExpression(item.expressionInStructure(0).text, item.expressionInStructure(0), ctx.text), ); } else { let itemStringResult = ''; @@ -412,7 +411,7 @@ export class Evaluator extends AbstractParseTreeVisitor implements LGTe switchExprs[0].text, switchExprs[0], switchcaseNodes[0].switchCaseStat().text, - switchErrorPrefix + switchErrorPrefix, ); let idx = 0; for (const caseNode of switchcaseNodes) { @@ -435,7 +434,7 @@ export class Evaluator extends AbstractParseTreeVisitor implements LGTe caseExprs[0].text, caseExprs[0], caseNode.switchCaseStat().text, - caseErrorPrefix + caseErrorPrefix, ); if (FunctionUtils.commonEquals(switchExprResult, caseExprResult)) { return this.visit(caseNode.normalTemplateBody()); @@ -460,7 +459,7 @@ export class Evaluator extends AbstractParseTreeVisitor implements LGTe .reverse() .join('') .replace(regex, (sub: string) => - this.evalExpression(sub.split('').reverse().join('')).toString().split('').reverse().join('') + this.evalExpression(sub.split('').reverse().join('')).toString().split('').reverse().join(''), ) .split('') .reverse() @@ -511,7 +510,7 @@ export class Evaluator extends AbstractParseTreeVisitor implements LGTe result: unknown, templateName: string, inlineContent = '', - errorPrefix = '' + errorPrefix = '', ): void { let errorMsg = ''; @@ -525,7 +524,7 @@ export class Evaluator extends AbstractParseTreeVisitor implements LGTe if (inlineContent && inlineContent.trim() !== '') { errorMsg = Evaluator.concatErrorMsg( errorMsg, - TemplateErrors.errorExpression(inlineContent, templateName, errorPrefix) + TemplateErrors.errorExpression(inlineContent, templateName, errorPrefix), ); } @@ -565,7 +564,7 @@ export class Evaluator extends AbstractParseTreeVisitor implements LGTe private evalExpressionInCondition( expressionContext: ParserRuleContext, contentLine: string, - errorPrefix = '' + errorPrefix = '', ): boolean { const exp = TemplateExtensions.trimExpression(expressionContext.text); const { value: result, error: error } = this.evalByAdaptiveExpression(exp, this.currentTarget().scope); @@ -592,7 +591,7 @@ export class Evaluator extends AbstractParseTreeVisitor implements LGTe exp: string, expressionContext?: ParserRuleContext, inlineContent = '', - errorPrefix = '' + errorPrefix = '', ): unknown { exp = TemplateExtensions.trimExpression(exp); const { value: result, error: error } = this.evalByAdaptiveExpression(exp, this.currentTarget().scope); @@ -623,117 +622,146 @@ export class Evaluator extends AbstractParseTreeVisitor implements LGTe } // Genearte a new lookup function based on one lookup function - private readonly customizedEvaluatorLookup = (baseLookup: EvaluatorLookup) => ( - name: string - ): ExpressionEvaluator => { - const standardFunction = baseLookup(name); + private readonly customizedEvaluatorLookup = + (baseLookup: EvaluatorLookup) => + (name: string): ExpressionEvaluator => { + const standardFunction = baseLookup(name); - if (standardFunction !== undefined) { - return standardFunction; - } + if (standardFunction !== undefined) { + return standardFunction; + } + + const pointIndex = name.indexOf('.'); + if (pointIndex > 0) { + const alias = name.substr(0, pointIndex); + const realTemplate = this.templates.namedReferences[alias]; + if (realTemplate) { + const realTemplateName = name.substr(pointIndex + 1); + return new ExpressionEvaluator( + realTemplateName, + FunctionUtils.apply(this.evaluateWithTemplates(realTemplateName, realTemplate)), + ReturnType.Object, + ); + } + } - const pointIndex = name.indexOf('.'); - if (pointIndex > 0) { - const alias = name.substr(0, pointIndex); - const realTemplate = this.templates.namedReferences[alias]; - if (realTemplate) { - const realTemplateName = name.substr(pointIndex + 1); + if (name.startsWith('lg.')) { + name = name.substring(3); + } + + const templateName = this.parseTemplateName(name).pureTemplateName; + if (templateName in this.templateMap) { return new ExpressionEvaluator( - realTemplateName, - FunctionUtils.apply(this.evaluateWithTemplates(realTemplateName, realTemplate)), - ReturnType.Object + templateName, + FunctionUtils.apply(this.templateEvaluator(name)), + ReturnType.Object, + this.validTemplateReference, ); } - } - if (name.startsWith('lg.')) { - name = name.substring(3); - } - - const templateName = this.parseTemplateName(name).pureTemplateName; - if (templateName in this.templateMap) { - return new ExpressionEvaluator( - templateName, - FunctionUtils.apply(this.templateEvaluator(name)), - ReturnType.Object, - this.validTemplateReference - ); - } + if (name === Evaluator.templateFunctionName) { + return new ExpressionEvaluator( + Evaluator.templateFunctionName, + FunctionUtils.apply(this.templateFunction()), + ReturnType.Object, + this.validateTemplateFunction, + ); + } - if (name === Evaluator.templateFunctionName) { - return new ExpressionEvaluator( - Evaluator.templateFunctionName, - FunctionUtils.apply(this.templateFunction()), - ReturnType.Object, - this.validateTemplateFunction - ); - } + if (Templates.enableFromFile) { + if (name === Evaluator.fromFileFunctionName) { + return new ExpressionEvaluator( + Evaluator.fromFileFunctionName, + FunctionUtils.apply(this.fromFile()), + ReturnType.Object, + (expr): void => FunctionUtils.validateOrder(expr, [ReturnType.String], ReturnType.String), + ); + } + } - if (Templates.enableFromFile) { - if (name === Evaluator.fromFileFunctionName) { + if (name === Evaluator.activityAttachmentFunctionName) { return new ExpressionEvaluator( - Evaluator.fromFileFunctionName, - FunctionUtils.apply(this.fromFile()), + Evaluator.activityAttachmentFunctionName, + FunctionUtils.apply(this.activityAttachment()), ReturnType.Object, - (expr): void => FunctionUtils.validateOrder(expr, [ReturnType.String], ReturnType.String) + (expr): void => FunctionUtils.validateOrder(expr, undefined, ReturnType.Object, ReturnType.String), ); } - } - if (name === Evaluator.activityAttachmentFunctionName) { - return new ExpressionEvaluator( - Evaluator.activityAttachmentFunctionName, - FunctionUtils.apply(this.activityAttachment()), - ReturnType.Object, - (expr): void => FunctionUtils.validateOrder(expr, undefined, ReturnType.Object, ReturnType.String) - ); - } + if (name === Evaluator.isTemplateFunctionName) { + return new ExpressionEvaluator( + Evaluator.isTemplateFunctionName, + FunctionUtils.apply(this.isTemplate()), + ReturnType.Boolean, + FunctionUtils.validateUnaryString, + ); + } - if (name === Evaluator.isTemplateFunctionName) { - return new ExpressionEvaluator( - Evaluator.isTemplateFunctionName, - FunctionUtils.apply(this.isTemplate()), - ReturnType.Boolean, - FunctionUtils.validateUnaryString - ); - } + if (name === Evaluator.expandTextFunctionName) { + return new ExpressionEvaluator( + Evaluator.expandTextFunctionName, + FunctionUtils.apply(this.expandText()), + ReturnType.Object, + FunctionUtils.validateUnaryString, + ); + } - if (name === Evaluator.expandTextFunctionName) { - return new ExpressionEvaluator( - Evaluator.expandTextFunctionName, - FunctionUtils.apply(this.expandText()), - ReturnType.Object, - FunctionUtils.validateUnaryString - ); - } + return undefined; + }; - return undefined; - }; + private readonly isTemplate = + () => + (args: readonly unknown[]): boolean => { + const templateName = args[0].toString(); + return templateName in this.templateMap; + }; - private readonly isTemplate = () => (args: readonly unknown[]): boolean => { - const templateName = args[0].toString(); - return templateName in this.templateMap; - }; + private readonly fromFile = + () => + (args: readonly unknown[]): unknown => { + const filePath: string = TemplateExtensions.normalizePath(args[0].toString()); + const resourcePath: string = this.getResourcePath(filePath); + let format = FileFormat.Evaluated; + if (args.length > 1) { + const expected = args[1].toString().toLowerCase(); + const currentFormat = Object.values(FileFormat).find((f) => f.toLowerCase() === expected); + if (currentFormat != null) { + format = currentFormat; + } + } - private readonly fromFile = () => (args: readonly unknown[]): unknown => { - const filePath: string = TemplateExtensions.normalizePath(args[0].toString()); - const resourcePath: string = this.getResourcePath(filePath); - let format = FileFormat.Evaluated; - if (args.length > 1) { - const expected = args[1].toString().toLowerCase(); - const currentFormat = Object.values(FileFormat).find((f) => f.toLowerCase() === expected); - if (currentFormat != null) { - format = currentFormat; + let result: unknown; + if (format === FileFormat.Binary) { + result = fs.readFileSync(resourcePath); + } else if (format === FileFormat.Raw) { + result = fs.readFileSync(resourcePath, 'utf-8'); + } else { + const stringContent = fs.readFileSync(resourcePath, 'utf-8'); + + const newScope = this.evaluationTargetStack.length > 0 ? this.currentTarget().scope : undefined; + const newTemplates = new Templates( + this.templates.allTemplates, + undefined, + undefined, + undefined, + undefined, + undefined, + this.expressionParser, + undefined, + [], + undefined, + this.templates.namedReferences, + ); + result = newTemplates.evaluateText(stringContent, newScope, this.lgOptions); } - } - let result: unknown; - if (format === FileFormat.Binary) { - result = fs.readFileSync(resourcePath); - } else if (format === FileFormat.Raw) { - result = fs.readFileSync(resourcePath, 'utf-8'); - } else { - const stringContent = fs.readFileSync(resourcePath, 'utf-8'); + return result; + }; + + private readonly expandText = + () => + (args: readonly unknown[]): unknown => { + const stringContent = args[0].toString(); const newScope = this.evaluationTargetStack.length > 0 ? this.currentTarget().scope : undefined; const newTemplates = new Templates( @@ -747,33 +775,10 @@ export class Evaluator extends AbstractParseTreeVisitor implements LGTe undefined, [], undefined, - this.templates.namedReferences + this.templates.namedReferences, ); - result = newTemplates.evaluateText(stringContent, newScope, this.lgOptions); - } - - return result; - }; - - private readonly expandText = () => (args: readonly unknown[]): unknown => { - const stringContent = args[0].toString(); - - const newScope = this.evaluationTargetStack.length > 0 ? this.currentTarget().scope : undefined; - const newTemplates = new Templates( - this.templates.allTemplates, - undefined, - undefined, - undefined, - undefined, - undefined, - this.expressionParser, - undefined, - [], - undefined, - this.templates.namedReferences - ); - return newTemplates.evaluateText(stringContent, newScope, this.lgOptions); - }; + return newTemplates.evaluateText(stringContent, newScope, this.lgOptions); + }; /** * @private @@ -801,28 +806,32 @@ export class Evaluator extends AbstractParseTreeVisitor implements LGTe return resourcePath; } - private readonly activityAttachment = () => (args: readonly unknown[]): unknown => { - return { - [Evaluator.LGType]: 'attachment', - contenttype: args[1].toString(), - content: args[0], + private readonly activityAttachment = + () => + (args: readonly unknown[]): unknown => { + return { + [Evaluator.LGType]: 'attachment', + contenttype: args[1].toString(), + content: args[0], + }; }; - }; - private readonly evaluateWithTemplates = (templateName: string, templates: Templates) => ( - args: readonly unknown[] - ): unknown => { - const newScope = this.constructScope(templateName, args.slice(0), templates.allTemplates); + private readonly evaluateWithTemplates = + (templateName: string, templates: Templates) => + (args: readonly unknown[]): unknown => { + const newScope = this.constructScope(templateName, args.slice(0), templates.allTemplates); - return templates.evaluate(templateName, newScope); - }; + return templates.evaluate(templateName, newScope); + }; - private readonly templateFunction = () => (args: readonly unknown[]): unknown => { - const templateName: string = args[0].toString(); - const newScope = this.constructScope(templateName, args.slice(1), this.templates.allTemplates); + private readonly templateFunction = + () => + (args: readonly unknown[]): unknown => { + const templateName: string = args[0].toString(); + const newScope = this.constructScope(templateName, args.slice(1), this.templates.allTemplates); - return this.evaluateTemplate(templateName, newScope); - }; + return this.evaluateTemplate(templateName, newScope); + }; private readonly validateTemplateFunction = (expression: Expression): void => { FunctionUtils.validateAtLeastOne(expression); @@ -857,11 +866,13 @@ export class Evaluator extends AbstractParseTreeVisitor implements LGTe } } - private readonly templateEvaluator = (templateName: string) => (args: readonly unknown[]): unknown => { - const newScope = this.constructScope(templateName, Array.from(args), this.templates.allTemplates); + private readonly templateEvaluator = + (templateName: string) => + (args: readonly unknown[]): unknown => { + const newScope = this.constructScope(templateName, Array.from(args), this.templates.allTemplates); - return this.evaluateTemplate(templateName, newScope); - }; + return this.evaluateTemplate(templateName, newScope); + }; private readonly validTemplateReference = (expression: Expression): void => { return this.checkTemplateReference(expression.type, expression.children); diff --git a/libraries/botbuilder-lg/src/expander.ts b/libraries/botbuilder-lg/src/expander.ts index 273f22b689..e235ea3056 100644 --- a/libraries/botbuilder-lg/src/expander.ts +++ b/libraries/botbuilder-lg/src/expander.ts @@ -1,4 +1,3 @@ -/* eslint-disable security/detect-object-injection */ /* eslint-disable security/detect-non-literal-fs-filename */ /** * @module botbuilder-lg @@ -20,7 +19,7 @@ import { Template } from './template'; import { TemplateErrors } from './templateErrors'; import { TemplateExtensions } from './templateExtensions'; import { Templates } from './templates'; -import keyBy = require('lodash/keyBy'); +import keyBy from 'lodash/keyBy'; import { Constant, @@ -96,10 +95,10 @@ export class Expander extends AbstractParseTreeVisitor implements LGT // Generate a new customized expression parser by injecting the template as functions. this.expanderExpressionParser = new ExpressionParser( - this.customizedEvaluatorLookup(templates.expressionParser.EvaluatorLookup, true) + this.customizedEvaluatorLookup(templates.expressionParser.EvaluatorLookup, true), ); this.evaluatorExpressionParser = new ExpressionParser( - this.customizedEvaluatorLookup(templates.expressionParser.EvaluatorLookup, false) + this.customizedEvaluatorLookup(templates.expressionParser.EvaluatorLookup, false), ); } @@ -124,7 +123,7 @@ export class Expander extends AbstractParseTreeVisitor implements LGT `${TemplateErrors.loopDetected} ${this.evaluationTargetStack .reverse() .map((u: EvaluationTarget): string => u.templateName) - .join(' => ')}` + .join(' => ')}`, ); } @@ -229,7 +228,7 @@ export class Expander extends AbstractParseTreeVisitor implements LGT if (x !== undefined && x !== null) { propertyObjects.push(x); } - } + }, ); const tempResult = []; for (const res of expandedResult) { @@ -284,7 +283,7 @@ export class Expander extends AbstractParseTreeVisitor implements LGT for (const item of values) { if (TemplateExtensions.isPureExpression(item)) { result.push( - this.evalExpression(item.expressionInStructure(0).text, item.expressionInStructure(0), ctx.text) + this.evalExpression(item.expressionInStructure(0).text, item.expressionInStructure(0), ctx.text), ); } else { let itemStringResult: unknown[] = ['']; @@ -293,7 +292,7 @@ export class Expander extends AbstractParseTreeVisitor implements LGT const errorPrefix = `Property '${ctx.STRUCTURE_IDENTIFIER().text}':`; itemStringResult = this.stringArrayConcat( itemStringResult, - this.evalExpression(child.text, child, ctx.text, errorPrefix) + this.evalExpression(child.text, child, ctx.text, errorPrefix), ); } else { const node = child as TerminalNode; @@ -333,7 +332,7 @@ export class Expander extends AbstractParseTreeVisitor implements LGT switchExprs[0].text, switchExprs[0], switchcaseNodes[0].switchCaseStat().text, - switchErrorPrefix + switchErrorPrefix, ); let idx = 0; for (const caseNode of switchcaseNodes) { @@ -357,7 +356,7 @@ export class Expander extends AbstractParseTreeVisitor implements LGT caseExprs[0].text, caseExprs[0], caseNode.switchCaseStat().text, - caseErrorPrefix + caseErrorPrefix, ); if (FunctionUtils.commonEquals(switchExprResult[0], caseExprResult[0])) { return this.visit(caseNode.normalTemplateBody()); @@ -382,7 +381,7 @@ export class Expander extends AbstractParseTreeVisitor implements LGT if (child instanceof ExpressionContext) { result = this.stringArrayConcat( result, - this.evalExpression(child.text, child, ctx.text, prefixErrorMsg) + this.evalExpression(child.text, child, ctx.text, prefixErrorMsg), ); } else { const node = child as TerminalNode; @@ -478,7 +477,7 @@ export class Expander extends AbstractParseTreeVisitor implements LGT private evalExpressionInCondition( expressionContext: ParserRuleContext, contentLine: string, - errorPrefix = '' + errorPrefix = '', ): boolean { const exp = TemplateExtensions.trimExpression(expressionContext.text); const { value: result, error: error } = this.evalByAdaptiveExpression(exp, this.currentTarget().scope); @@ -566,124 +565,128 @@ export class Expander extends AbstractParseTreeVisitor implements LGT return str1.toString() + str2.toString(); } - private readonly customizedEvaluatorLookup = (baseLookup: EvaluatorLookup, isExpander: boolean) => ( - name: string - ): ExpressionEvaluator => { - const standardFunction = baseLookup(name); + private readonly customizedEvaluatorLookup = + (baseLookup: EvaluatorLookup, isExpander: boolean) => + (name: string): ExpressionEvaluator => { + const standardFunction = baseLookup(name); - if (standardFunction !== undefined) { - return standardFunction; - } + if (standardFunction !== undefined) { + return standardFunction; + } - const pointIndex = name.indexOf('.'); - if (pointIndex > 0) { - const alias = name.substr(0, pointIndex); - const realTemplate = this.templates.namedReferences[alias]; - if (realTemplate) { - const realTemplateName = name.substr(pointIndex + 1); - return new ExpressionEvaluator( - realTemplateName, - FunctionUtils.apply(this.evaluateWithTemplates(realTemplateName, realTemplate)), - ReturnType.Object - ); + const pointIndex = name.indexOf('.'); + if (pointIndex > 0) { + const alias = name.substr(0, pointIndex); + const realTemplate = this.templates.namedReferences[alias]; + if (realTemplate) { + const realTemplateName = name.substr(pointIndex + 1); + return new ExpressionEvaluator( + realTemplateName, + FunctionUtils.apply(this.evaluateWithTemplates(realTemplateName, realTemplate)), + ReturnType.Object, + ); + } } - } - if (name.startsWith('lg.')) { - name = name.substring(3); - } + if (name.startsWith('lg.')) { + name = name.substring(3); + } - const templateName = this.parseTemplateName(name).pureTemplateName; - if (templateName in this.templateMap) { - if (isExpander) { + const templateName = this.parseTemplateName(name).pureTemplateName; + if (templateName in this.templateMap) { + if (isExpander) { + return new ExpressionEvaluator( + templateName, + FunctionUtils.apply(this.templateExpander(name)), + ReturnType.Object, + this.validTemplateReference, + ); + } else { + return new ExpressionEvaluator( + templateName, + FunctionUtils.apply(this.templateEvaluator(name)), + ReturnType.Object, + this.validTemplateReference, + ); + } + } + + if (name === Evaluator.templateFunctionName) { return new ExpressionEvaluator( - templateName, - FunctionUtils.apply(this.templateExpander(name)), + Evaluator.templateFunctionName, + FunctionUtils.apply(this.templateFunction()), ReturnType.Object, - this.validTemplateReference + this.validateTemplateFunction, ); - } else { + } + + if (Templates.enableFromFile) { + if (name === Evaluator.fromFileFunctionName) { + return new ExpressionEvaluator( + Evaluator.fromFileFunctionName, + FunctionUtils.apply(this.fromFile()), + ReturnType.Object, + (expr): void => FunctionUtils.validateOrder(expr, [ReturnType.String], ReturnType.String), + ); + } + } + + if (name === Evaluator.activityAttachmentFunctionName) { return new ExpressionEvaluator( - templateName, - FunctionUtils.apply(this.templateEvaluator(name)), + Evaluator.activityAttachmentFunctionName, + FunctionUtils.apply(this.activityAttachment()), ReturnType.Object, - this.validTemplateReference + (expr): void => FunctionUtils.validateOrder(expr, undefined, ReturnType.Object, ReturnType.String), ); } - } - if (name === Evaluator.templateFunctionName) { - return new ExpressionEvaluator( - Evaluator.templateFunctionName, - FunctionUtils.apply(this.templateFunction()), - ReturnType.Object, - this.validateTemplateFunction - ); - } + if (name === Evaluator.isTemplateFunctionName) { + return new ExpressionEvaluator( + Evaluator.isTemplateFunctionName, + FunctionUtils.apply(this.isTemplate()), + ReturnType.Boolean, + FunctionUtils.validateUnaryString, + ); + } - if (Templates.enableFromFile) { - if (name === Evaluator.fromFileFunctionName) { + if (name === Evaluator.expandTextFunctionName) { return new ExpressionEvaluator( - Evaluator.fromFileFunctionName, - FunctionUtils.apply(this.fromFile()), + Evaluator.expandTextFunctionName, + FunctionUtils.apply(this.expandText()), ReturnType.Object, - (expr): void => FunctionUtils.validateOrder(expr, [ReturnType.String], ReturnType.String) + FunctionUtils.validateUnaryString, ); } - } - - if (name === Evaluator.activityAttachmentFunctionName) { - return new ExpressionEvaluator( - Evaluator.activityAttachmentFunctionName, - FunctionUtils.apply(this.activityAttachment()), - ReturnType.Object, - (expr): void => FunctionUtils.validateOrder(expr, undefined, ReturnType.Object, ReturnType.String) - ); - } - - if (name === Evaluator.isTemplateFunctionName) { - return new ExpressionEvaluator( - Evaluator.isTemplateFunctionName, - FunctionUtils.apply(this.isTemplate()), - ReturnType.Boolean, - FunctionUtils.validateUnaryString - ); - } - - if (name === Evaluator.expandTextFunctionName) { - return new ExpressionEvaluator( - Evaluator.expandTextFunctionName, - FunctionUtils.apply(this.expandText()), - ReturnType.Object, - FunctionUtils.validateUnaryString - ); - } - return undefined; - }; + return undefined; + }; - private readonly evaluateWithTemplates = (templateName: string, templates: Templates) => ( - args: readonly unknown[] - ): unknown => { - const newScope = this.constructScope(templateName, args.slice(0), templates.allTemplates); + private readonly evaluateWithTemplates = + (templateName: string, templates: Templates) => + (args: readonly unknown[]): unknown => { + const newScope = this.constructScope(templateName, args.slice(0), templates.allTemplates); - return templates.evaluate(templateName, newScope); - }; + return templates.evaluate(templateName, newScope); + }; - private readonly templateEvaluator = (templateName: string) => (args: readonly unknown[]): unknown => { - const newScope = this.constructScope(templateName, Array.from(args), this.templates.allTemplates); + private readonly templateEvaluator = + (templateName: string) => + (args: readonly unknown[]): unknown => { + const newScope = this.constructScope(templateName, Array.from(args), this.templates.allTemplates); - const value = this.expandTemplate(templateName, newScope); - const randomNumber = Extensions.randomNext(this.currentTarget().scope, 0, value.length); + const value = this.expandTemplate(templateName, newScope); + const randomNumber = Extensions.randomNext(this.currentTarget().scope, 0, value.length); - return value[randomNumber]; - }; + return value[randomNumber]; + }; - private readonly templateExpander = (templateName: string) => (args: readonly unknown[]): unknown[] => { - const newScope = this.constructScope(templateName, Array.from(args), this.templates.allTemplates); + private readonly templateExpander = + (templateName: string) => + (args: readonly unknown[]): unknown[] => { + const newScope = this.constructScope(templateName, Array.from(args), this.templates.allTemplates); - return this.expandTemplate(templateName, newScope); - }; + return this.expandTemplate(templateName, newScope); + }; /** * @private @@ -691,7 +694,7 @@ export class Expander extends AbstractParseTreeVisitor implements LGT private reconstructExpression( expanderExpression: Expression, evaluatorExpression: Expression, - foundPrebuiltFunction: boolean + foundPrebuiltFunction: boolean, ): Expression { if (this.templateMap[expanderExpression.type]) { if (foundPrebuiltFunction) { @@ -705,37 +708,66 @@ export class Expander extends AbstractParseTreeVisitor implements LGT expanderExpression.children[i] = this.reconstructExpression( expanderExpression.children[i], evaluatorExpression.children[i], - foundPrebuiltFunction + foundPrebuiltFunction, ); } return expanderExpression; } - private readonly isTemplate = () => (args: readonly unknown[]): boolean => { - const templateName = args[0].toString(); - return templateName in this.templateMap; - }; + private readonly isTemplate = + () => + (args: readonly unknown[]): boolean => { + const templateName = args[0].toString(); + return templateName in this.templateMap; + }; - private readonly fromFile = () => (args: readonly unknown[]): unknown => { - const filePath: string = TemplateExtensions.normalizePath(args[0].toString()); - const resourcePath: string = this.getResourcePath(filePath); - let format = FileFormat.Evaluated; - if (args.length > 1) { - const expected = args[1].toString().toLowerCase(); - const currentFormat = Object.values(FileFormat).find((f) => f.toLowerCase() === expected); - if (currentFormat != null) { - format = currentFormat; + private readonly fromFile = + () => + (args: readonly unknown[]): unknown => { + const filePath: string = TemplateExtensions.normalizePath(args[0].toString()); + const resourcePath: string = this.getResourcePath(filePath); + let format = FileFormat.Evaluated; + if (args.length > 1) { + const expected = args[1].toString().toLowerCase(); + const currentFormat = Object.values(FileFormat).find((f) => f.toLowerCase() === expected); + if (currentFormat != null) { + format = currentFormat; + } } - } - let result: unknown; - if (format === FileFormat.Binary) { - result = fs.readFileSync(resourcePath); - } else if (format === FileFormat.Raw) { - result = fs.readFileSync(resourcePath, 'utf-8'); - } else { - const stringContent = fs.readFileSync(resourcePath, 'utf-8'); + let result: unknown; + if (format === FileFormat.Binary) { + result = fs.readFileSync(resourcePath); + } else if (format === FileFormat.Raw) { + result = fs.readFileSync(resourcePath, 'utf-8'); + } else { + const stringContent = fs.readFileSync(resourcePath, 'utf-8'); + + const newScope = this.evaluationTargetStack.length > 0 ? this.currentTarget().scope : undefined; + const newTemplates = new Templates( + this.templates.allTemplates, + undefined, + undefined, + undefined, + undefined, + undefined, + this.templates.expressionParser, + undefined, + [], + undefined, + this.templates.namedReferences, + ); + result = newTemplates.evaluateText(stringContent, newScope, this.lgOptions); + } + + return result; + }; + + private readonly expandText = + () => + (args: readonly unknown[]): unknown => { + const stringContent = args[0].toString(); const newScope = this.evaluationTargetStack.length > 0 ? this.currentTarget().scope : undefined; const newTemplates = new Templates( @@ -749,33 +781,10 @@ export class Expander extends AbstractParseTreeVisitor implements LGT undefined, [], undefined, - this.templates.namedReferences + this.templates.namedReferences, ); - result = newTemplates.evaluateText(stringContent, newScope, this.lgOptions); - } - - return result; - }; - - private readonly expandText = () => (args: readonly unknown[]): unknown => { - const stringContent = args[0].toString(); - - const newScope = this.evaluationTargetStack.length > 0 ? this.currentTarget().scope : undefined; - const newTemplates = new Templates( - this.templates.allTemplates, - undefined, - undefined, - undefined, - undefined, - undefined, - this.templates.expressionParser, - undefined, - [], - undefined, - this.templates.namedReferences - ); - return newTemplates.evaluateText(stringContent, newScope, this.lgOptions); - }; + return newTemplates.evaluateText(stringContent, newScope, this.lgOptions); + }; /** * @private @@ -803,21 +812,25 @@ export class Expander extends AbstractParseTreeVisitor implements LGT return resourcePath; } - private readonly activityAttachment = () => (args: readonly unknown[]): Record => { - return { - [Evaluator.LGType]: 'attachment', - contenttype: args[1].toString(), - content: args[0], + private readonly activityAttachment = + () => + (args: readonly unknown[]): Record => { + return { + [Evaluator.LGType]: 'attachment', + contenttype: args[1].toString(), + content: args[0], + }; }; - }; - private readonly templateFunction = () => (args: readonly unknown[]): unknown[] => { - const templateName: string = args[0].toString(); - const newScope = this.constructScope(templateName, args.slice(1), this.templates.allTemplates); - const value = this.expandTemplate(templateName, newScope); + private readonly templateFunction = + () => + (args: readonly unknown[]): unknown[] => { + const templateName: string = args[0].toString(); + const newScope = this.constructScope(templateName, args.slice(1), this.templates.allTemplates); + const value = this.expandTemplate(templateName, newScope); - return value; - }; + return value; + }; private readonly validateTemplateFunction = (expression: Expression): void => { FunctionUtils.validateAtLeastOne(expression); diff --git a/libraries/botbuilder-lg/src/extractor.ts b/libraries/botbuilder-lg/src/extractor.ts index 22543f43d0..3df5a8d2db 100644 --- a/libraries/botbuilder-lg/src/extractor.ts +++ b/libraries/botbuilder-lg/src/extractor.ts @@ -6,7 +6,7 @@ * Licensed under the MIT License. */ import { AbstractParseTreeVisitor, TerminalNode } from 'antlr4ts/tree'; -import keyBy = require('lodash/keyBy'); +import keyBy from 'lodash/keyBy'; import { LGTemplateParserVisitor } from './generated/LGTemplateParserVisitor'; import { Template } from './template'; @@ -26,7 +26,8 @@ import { */ export class Extractor extends AbstractParseTreeVisitor> - implements LGTemplateParserVisitor> { + implements LGTemplateParserVisitor> +{ readonly templates: Template[]; readonly templateMap: Record; @@ -55,7 +56,7 @@ export class Extractor const templateBodies = this.visit(template.templateBodyParseTree); let isNormalTemplate = true; templateBodies.forEach( - (templateBody) => (isNormalTemplate = isNormalTemplate && templateBody === undefined) + (templateBody) => (isNormalTemplate = isNormalTemplate && templateBody === undefined), ); if (isNormalTemplate) { @@ -128,8 +129,8 @@ export class Extractor const node: TerminalNode = ifExpr ? conditionNode.IF() : elseIfExpr - ? conditionNode.ELSEIF() - : conditionNode.ELSE(); + ? conditionNode.ELSEIF() + : conditionNode.ELSE(); const conditionLabel: string = node.text.toLowerCase(); const childTemplateBodyResult: string[] = []; const templateBodies = this.visit(ifRule.normalTemplateBody()); @@ -167,8 +168,8 @@ export class Extractor const node: TerminalNode = switchExpr ? switchCaseStat.SWITCH() : caseExpr - ? switchCaseStat.CASE() - : switchCaseStat.DEFAULT(); + ? switchCaseStat.CASE() + : switchCaseStat.DEFAULT(); if (switchExpr) { continue; } diff --git a/libraries/botbuilder-lg/src/index.ts b/libraries/botbuilder-lg/src/index.ts index 0c10a62236..a7b32eb138 100644 --- a/libraries/botbuilder-lg/src/index.ts +++ b/libraries/botbuilder-lg/src/index.ts @@ -22,7 +22,6 @@ export * from './evaluationTarget'; export * from './templateExtensions'; export * from './analyzerResult'; export * from './templateErrors'; -export * from './evaluator'; export * from './errorListener'; export * from './customizedMemory'; export * from './expander'; diff --git a/libraries/botbuilder-lg/src/multiLanguageLG.ts b/libraries/botbuilder-lg/src/multiLanguageLG.ts index c29562a06d..42789c1b11 100644 --- a/libraries/botbuilder-lg/src/multiLanguageLG.ts +++ b/libraries/botbuilder-lg/src/multiLanguageLG.ts @@ -877,7 +877,7 @@ export class MultiLanguageLG { constructor( templatesPerLocale: Map | undefined, filePerLocale: Map | undefined, - defaultLanguage?: string + defaultLanguage?: string, ) { if (templatesPerLocale !== undefined) { this.lgPerLocale = templatesPerLocale; diff --git a/libraries/botbuilder-lg/src/staticChecker.ts b/libraries/botbuilder-lg/src/staticChecker.ts index fe7cc100ba..21d930d494 100644 --- a/libraries/botbuilder-lg/src/staticChecker.ts +++ b/libraries/botbuilder-lg/src/staticChecker.ts @@ -35,7 +35,8 @@ import { */ export class StaticChecker extends AbstractParseTreeVisitor - implements LGTemplateParserVisitor { + implements LGTemplateParserVisitor +{ private readonly templates: Templates; private currentTemplate: Template; private _expressionParser: ExpressionParserInterface; @@ -77,7 +78,7 @@ export class StaticChecker Range.DefaultRange, TemplateErrors.noTemplate, DiagnosticSeverity.Warning, - this.templates.source + this.templates.source, ); result.push(diagnostic); return result; @@ -96,10 +97,10 @@ export class StaticChecker range, TemplateErrors.duplicatedTemplateInDiffTemplate( sameTemplate.name, - sameTemplate.sourceRange.source + sameTemplate.sourceRange.source, ), DiagnosticSeverity.Error, - this.templates.source + this.templates.source, ); templateDiagnostics.push(diagnostic); } @@ -151,8 +152,8 @@ export class StaticChecker this.buildLGDiagnostic( TemplateErrors.invalidStrucName(errorName.text), undefined, - context.structuredBodyNameLine() - ) + context.structuredBodyNameLine(), + ), ); } @@ -209,12 +210,12 @@ export class StaticChecker const node: TerminalNode = ifExpr ? conditionNode.IF() : elseIfExpr - ? conditionNode.ELSEIF() - : conditionNode.ELSE(); + ? conditionNode.ELSEIF() + : conditionNode.ELSE(); if (node.text.split(' ').length - 1 > 1) { result.push( - this.buildLGDiagnostic(TemplateErrors.invalidWhitespaceInCondition, undefined, conditionNode) + this.buildLGDiagnostic(TemplateErrors.invalidWhitespaceInCondition, undefined, conditionNode), ); } @@ -223,8 +224,8 @@ export class StaticChecker this.buildLGDiagnostic( TemplateErrors.notStartWithIfInCondition, DiagnosticSeverity.Warning, - conditionNode - ) + conditionNode, + ), ); } @@ -237,8 +238,8 @@ export class StaticChecker this.buildLGDiagnostic( TemplateErrors.notEndWithElseInCondition, DiagnosticSeverity.Warning, - conditionNode - ) + conditionNode, + ), ); } @@ -249,7 +250,7 @@ export class StaticChecker if (!elseExpr) { if (ifRule.ifCondition().expression().length !== 1) { result.push( - this.buildLGDiagnostic(TemplateErrors.invalidExpressionInCondition, undefined, conditionNode) + this.buildLGDiagnostic(TemplateErrors.invalidExpressionInCondition, undefined, conditionNode), ); } else { const errorPrefix = "Condition '" + conditionNode.expression(0).text + "': "; @@ -258,7 +259,7 @@ export class StaticChecker } else { if (ifRule.ifCondition().expression().length !== 0) { result.push( - this.buildLGDiagnostic(TemplateErrors.extraExpressionInCondition, undefined, conditionNode) + this.buildLGDiagnostic(TemplateErrors.extraExpressionInCondition, undefined, conditionNode), ); } } @@ -266,7 +267,7 @@ export class StaticChecker result = result.concat(this.visit(ifRule.normalTemplateBody())); } else { result.push( - this.buildLGDiagnostic(TemplateErrors.missingTemplateBodyInCondition, undefined, conditionNode) + this.buildLGDiagnostic(TemplateErrors.missingTemplateBodyInCondition, undefined, conditionNode), ); } @@ -296,23 +297,27 @@ export class StaticChecker const node: TerminalNode = switchExpr ? switchCaseStat.SWITCH() : caseExpr - ? switchCaseStat.CASE() - : switchCaseStat.DEFAULT(); + ? switchCaseStat.CASE() + : switchCaseStat.DEFAULT(); if (node.text.split(' ').length - 1 > 1) { result.push( - this.buildLGDiagnostic(TemplateErrors.invalidWhitespaceInSwitchCase, undefined, switchCaseStat) + this.buildLGDiagnostic(TemplateErrors.invalidWhitespaceInSwitchCase, undefined, switchCaseStat), ); } if (idx === 0 && !switchExpr) { result.push( - this.buildLGDiagnostic(TemplateErrors.notStartWithSwitchInSwitchCase, undefined, switchCaseStat) + this.buildLGDiagnostic(TemplateErrors.notStartWithSwitchInSwitchCase, undefined, switchCaseStat), ); } if (idx > 0 && switchExpr) { result.push( - this.buildLGDiagnostic(TemplateErrors.multipleSwithStatementInSwitchCase, undefined, switchCaseStat) + this.buildLGDiagnostic( + TemplateErrors.multipleSwithStatementInSwitchCase, + undefined, + switchCaseStat, + ), ); } @@ -321,8 +326,8 @@ export class StaticChecker this.buildLGDiagnostic( TemplateErrors.invalidStatementInMiddlerOfSwitchCase, undefined, - switchCaseStat - ) + switchCaseStat, + ), ); } @@ -332,8 +337,8 @@ export class StaticChecker this.buildLGDiagnostic( TemplateErrors.notEndWithDefaultInSwitchCase, DiagnosticSeverity.Warning, - switchCaseStat - ) + switchCaseStat, + ), ); } else { if (length === 2) { @@ -341,8 +346,8 @@ export class StaticChecker this.buildLGDiagnostic( TemplateErrors.missingCaseInSwitchCase, DiagnosticSeverity.Warning, - switchCaseStat - ) + switchCaseStat, + ), ); } } @@ -350,7 +355,7 @@ export class StaticChecker if (switchExpr || caseExpr) { if (switchCaseStat.expression().length !== 1) { result.push( - this.buildLGDiagnostic(TemplateErrors.invalidExpressionInSwiathCase, undefined, switchCaseStat) + this.buildLGDiagnostic(TemplateErrors.invalidExpressionInSwiathCase, undefined, switchCaseStat), ); } else { let errorPrefix = switchExpr ? 'Switch' : 'Case'; @@ -360,7 +365,7 @@ export class StaticChecker } else { if (switchCaseStat.expression().length !== 0 || switchCaseStat.TEXT().length !== 0) { result.push( - this.buildLGDiagnostic(TemplateErrors.extraExpressionInSwitchCase, undefined, switchCaseStat) + this.buildLGDiagnostic(TemplateErrors.extraExpressionInSwitchCase, undefined, switchCaseStat), ); } } @@ -372,8 +377,8 @@ export class StaticChecker this.buildLGDiagnostic( TemplateErrors.missingTemplateBodyInSwitchCase, undefined, - switchCaseStat - ) + switchCaseStat, + ), ); } } @@ -446,7 +451,7 @@ export class StaticChecker private buildLGDiagnostic( message: string, severity: DiagnosticSeverity = undefined, - context: ParserRuleContext = undefined + context: ParserRuleContext = undefined, ): Diagnostic { const lineOffset = this.currentTemplate !== undefined ? this.currentTemplate.sourceRange.range.start.line : 0; diff --git a/libraries/botbuilder-lg/src/templateExtensions.ts b/libraries/botbuilder-lg/src/templateExtensions.ts index 0d1c49995b..ac08c37853 100644 --- a/libraries/botbuilder-lg/src/templateExtensions.ts +++ b/libraries/botbuilder-lg/src/templateExtensions.ts @@ -1,4 +1,3 @@ -/* eslint-disable security/detect-object-injection */ /** * @module botbuilder-lg */ @@ -188,7 +187,7 @@ export class TemplateExtensions { const startPosition = new Position(lineOffset + context.start.line, context.start.charPositionInLine); const stopPosition = new Position( lineOffset + context.stop.line, - context.stop.charPositionInLine + context.stop.text.length + context.stop.charPositionInLine + context.stop.text.length, ); return new Range(startPosition, stopPosition); diff --git a/libraries/botbuilder-lg/src/templates.ts b/libraries/botbuilder-lg/src/templates.ts index f4e9c2cd61..289bb0675f 100644 --- a/libraries/botbuilder-lg/src/templates.ts +++ b/libraries/botbuilder-lg/src/templates.ts @@ -1,4 +1,3 @@ -/* eslint-disable security/detect-object-injection */ /** * @module botbuilder-lg */ @@ -20,11 +19,10 @@ import { SimpleObjectMemory, ValueWithError, } from 'adaptive-expressions'; -import { ImportResolverDelegate, TemplatesTransformer } from './templatesParser'; +import { ImportResolverDelegate, TemplatesTransformer, TemplatesParser } from './templatesParser'; import { Evaluator } from './evaluator'; import { Expander } from './expander'; import { Analyzer } from './analyzer'; -import { TemplatesParser } from './templatesParser'; import { AnalyzerResult } from './analyzerResult'; import { TemplateErrors } from './templateErrors'; import { TemplateExtensions } from './templateExtensions'; @@ -133,7 +131,7 @@ export class Templates implements Iterable