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

Make the CRUD of the template consistent #1952

Merged
merged 2 commits into from
Mar 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 5 additions & 8 deletions libraries/botbuilder-lg/src/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/
import { TerminalNode } from 'antlr4ts/tree';
import { ParametersContext, TemplateDefinitionContext, TemplateNameContext, FileContext} from './generated/LGFileParser';
import { TemplateExtensions } from './templateExtensions';

/**
* Here is a data model that can easily understanded and used as the context or all kinds of visitors
Expand Down Expand Up @@ -97,19 +98,15 @@ export class Template {
}

private getRangeContent(originString: string, startLine: number, stopLine: number): string {
const originList: string[] = originString.split('\n');
if (startLine < 0 || startLine > stopLine || stopLine >= originList.length) {
if (startLine < 0 || startLine > stopLine) {
throw new Error(`index out of range.`);
}

const destList: string[] = originList.slice(startLine, stopLine + 1);
const originList: string[] = TemplateExtensions.readLine(originString);

let result: string = destList.join('\n');
if (result.endsWith('\r')) {
result = result.substr(0, result.length - 1);
}
const destList: string[] = originList.slice(startLine, stopLine + 1);

return result;
return destList.join('\r\n');
}

public toString(): string {
Expand Down
12 changes: 12 additions & 0 deletions libraries/botbuilder-lg/src/templateExtensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,16 @@ export class TemplateExtensions {
return v.toString(16);
});
}

/**
* read line from text.
* @param input text content.
*/
public static readLine(input: string): string[] {
if (!input) {
return [];
}

return input.replace(/\r\n/g, '\n').split('\n');
}
}
135 changes: 39 additions & 96 deletions libraries/botbuilder-lg/src/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { TemplateExtensions } from './templateExtensions';
* LG entrance, including properties that LG file has, and evaluate functions.
*/
export class Templates implements Iterable<Template> {
private readonly newLine: string = '\r\n';
private items: Template[];

/**
Expand Down Expand Up @@ -214,10 +215,8 @@ export class Templates implements Iterable<Template> {
* @param inlineStr inline string which will be evaluated.
* @param scope scope object or JToken.
*/
public evaluateText(inlineStr: string, scope?: object): any
{
if (inlineStr === undefined)
{
public evaluateText(inlineStr: string, scope?: object): any {
if (inlineStr === undefined) {
throw Error('inline string is empty');
}

Expand All @@ -230,7 +229,7 @@ export class Templates implements Iterable<Template> {
inlineStr = !(inlineStr.trim().startsWith(multiLineMark) && inlineStr.includes('\n'))
? `${ multiLineMark }${ inlineStr }${ multiLineMark }` : inlineStr;

const newContent = `#${ fakeTemplateId } \r\n - ${ inlineStr }`;
const newContent = `#${ fakeTemplateId } ${ this.newLine } - ${ inlineStr }`;

const newTemplates = TemplatesParser.parseTextWithRef(newContent, this);
return newTemplates.evaluate(fakeTemplateId, scope);
Expand All @@ -251,12 +250,12 @@ export class Templates implements Iterable<Template> {

const templateNameLine: string = this.buildTemplateNameLine(newTemplateName, parameters);
const newTemplateBody: string = this.convertTemplateBody(templateBody);
const content = `${ templateNameLine }\r\n${ newTemplateBody }\r\n`;
const content = `${ templateNameLine }${ this.newLine }${ newTemplateBody }`;

let startLine: number;
let stopLine: number;

({startLine, stopLine} = template.getTemplateRange());
({ startLine, stopLine } = template.getTemplateRange());
const newContent: string = this.replaceRangeContent(this.content, startLine, stopLine, content);
this.initialize(TemplatesParser.parseText(newContent, this.id, this.importResolver));

Expand All @@ -278,7 +277,7 @@ export class Templates implements Iterable<Template> {

const templateNameLine: string = this.buildTemplateNameLine(templateName, parameters);
const newTemplateBody: string = this.convertTemplateBody(templateBody);
const newContent = `${ this.content.trimRight() }\r\n\r\n${ templateNameLine }\r\n${ newTemplateBody }\r\n`;
const newContent = `${ this.content }${ this.newLine }${ templateNameLine }${ this.newLine }${ newTemplateBody }`;
this.initialize(TemplatesParser.parseText(newContent, this.id, this.importResolver));

return this;
Expand All @@ -298,7 +297,7 @@ export class Templates implements Iterable<Template> {
let startLine: number;
let stopLine: number;

({startLine, stopLine} = template.getTemplateRange());
({ startLine, stopLine } = template.getTemplateRange());

const newContent: string = this.replaceRangeContent(this.content, startLine, stopLine, undefined);
this.initialize(TemplatesParser.parseText(newContent, this.id, this.importResolver));
Expand All @@ -311,97 +310,46 @@ export class Templates implements Iterable<Template> {
}

private replaceRangeContent(originString: string, startLine: number, stopLine: number, replaceString: string): string {
const originList: string[] = originString.split('\n');
const destList: string[] = [];

if (startLine < 0 || startLine > stopLine || stopLine >= originList.length) {
if (startLine < 0 || startLine > stopLine) {
throw new Error('index out of range.');
}

destList.push(...this.trimList(originList.slice(0, startLine)));

if (stopLine < originList.length - 1) {
// insert at the middle of the content
destList.push('\r\n');
if (replaceString) {
destList.push(replaceString);
destList.push('\r\n');
}

destList.push(...this.trimList(originList.slice(stopLine + 1)));
} else {
// insert at the tail of the content
if (replaceString) {
destList.push('\r\n');
destList.push(replaceString);
}
}

return this.buildNewLGContent(this.trimList(destList));
}

/**
* trim the newlines at the beginning or at the tail of the array
* @param input input array
*/
private trimList(input: string[]): string[] {
if (input === undefined) {
return undefined;
}

let startIndex = 0;
let endIndex = input.length;

for(let i = 0; i< input.length; i++) {
if (input[i].trim() !== '') {
startIndex = i;
break;
}
}

for(let i = input.length - 1; i >= 0; i--) {
if (input[i].trim() !== '') {
endIndex = i + 1;
break;
}
}

return input.slice(startIndex, endIndex);
}

private buildNewLGContent(destList: string[]): string {
let result = '';
for (let i = 0; i < destList.length; i++) {
const currentItem: string = destList[i];
result = result.concat(currentItem);
if (currentItem.endsWith('\r')) {
result = result.concat('\n');
} else if (i < destList.length - 1 && !currentItem.endsWith('\r\n')) {
result = result.concat('\r\n');
const originList: string[] = TemplateExtensions.readLine(originString);
const destList: string[] = [];
let replaced = false;
for (let lineNumber = 0; lineNumber < originList.length; lineNumber++) {
if (lineNumber < startLine || lineNumber > stopLine) {
destList.push(originList[lineNumber]);
} else {
if (!replaced) {
replaced = true;
if (replaceString) {
destList.push(replaceString);
}
}
}
}

return result;
return destList.join(this.newLine);
}

private convertTemplateBody(templateBody: string): string {
if (!templateBody) {
return '';
}

const replaceList: string[] = templateBody.split('\n');
const wrappedReplaceList: string[] = replaceList.map((u: string): string => this.wrapTemplateBodyString(u));

return wrappedReplaceList.join('\n');
}
const replaceList: string[] = TemplateExtensions.readLine(templateBody);
const destList: string[] = replaceList.map((u: string): string => {
const isStartWithHash: boolean = u.trimLeft().startsWith('#');
if (isStartWithHash) {
return `- ${ u.trimLeft() }`;
} else {
return u;
}
});

private wrapTemplateBodyString(replaceItem: string): string {
const isStartWithHash: boolean = replaceItem.trimLeft().startsWith('#');
if (isStartWithHash) {
return `- ${ replaceItem.trimLeft() }`;
} else {
return replaceItem;
}
return destList.join(this.newLine);
}

private buildTemplateNameLine(templateName: string, parameters: string[]): string {
Expand Down Expand Up @@ -429,33 +377,28 @@ export class Templates implements Iterable<Template> {
if (this.allDiagnostics) {
const errors = this.allDiagnostics.filter((u): boolean => u.severity === DiagnosticSeverity.Error);
if (errors.length !== 0) {
throw Error(errors.join('\n'));
throw Error(errors.join(this.newLine));
}
}
}

private getStrictModeFromOptions(options: string[]): boolean {
let result = false;
if (!options)
{
if (!options) {
return result;
}

const strictModeKey = '@strict';
for (const option of options)
{
for (const option of options) {
if (option && option.includes('=')) {
const index = option.indexOf('=');
const key = option.substring(0, index).trim();
const value = option.substring(index + 1).trim().toLowerCase();
if (key === strictModeKey)
{
if (value === 'true')
{
if (key === strictModeKey) {
if (value === 'true') {
result = true;
}
else if (value == 'false')
{
else if (value == 'false') {
result = false;
}
}
Expand Down
8 changes: 4 additions & 4 deletions libraries/botbuilder-lg/tests/lg.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -545,12 +545,12 @@ describe('LG', function() {
assert.strictEqual(templates.toArray()[1].parameters.length, 2);
assert.strictEqual(templates.toArray()[1].parameters[0], 'age');
assert.strictEqual(templates.toArray()[1].parameters[1], 'name');
assert.strictEqual(templates.toArray()[1].body.replace(/\r\n/g, '\n'), '- hi \n');
assert.strictEqual(templates.toArray()[1].body.replace(/\r\n/g, '\n'), '- hi ');

templates = templates.addTemplate('newtemplate2', undefined, '- hi2 ');
assert.strictEqual(templates.toArray().length, 3);
assert.strictEqual(templates.toArray()[2].name, 'newtemplate2');
assert.strictEqual(templates.toArray()[2].body.replace(/\r\n/g, '\n'), '- hi2 \n');
assert.strictEqual(templates.toArray()[2].body.replace(/\r\n/g, '\n'), '- hi2 ');

templates = templates.updateTemplate('newtemplate', 'newtemplateName', ['newage', 'newname'], '- new hi\r\n#hi');
assert.strictEqual(templates.toArray().length, 3);
Expand All @@ -559,13 +559,13 @@ describe('LG', function() {
assert.strictEqual(templates.toArray()[1].parameters.length, 2);
assert.strictEqual(templates.toArray()[1].parameters[0], 'newage');
assert.strictEqual(templates.toArray()[1].parameters[1], 'newname');
assert.strictEqual(templates.toArray()[1].body.replace(/\r\n/g, '\n'), '- new hi\n- #hi\n');
assert.strictEqual(templates.toArray()[1].body.replace(/\r\n/g, '\n'), '- new hi\n- #hi');

templates = templates.updateTemplate('newtemplate2', 'newtemplateName2', ['newage2', 'newname2'], '- new hi\r\n#hi2');
assert.strictEqual(templates.toArray().length, 3);
assert.strictEqual(templates.imports.length, 0);
assert.strictEqual(templates.toArray()[2].name, 'newtemplateName2');
assert.strictEqual(templates.toArray()[2].body.replace(/\r\n/g, '\n'), '- new hi\n- #hi2\n');
assert.strictEqual(templates.toArray()[2].body.replace(/\r\n/g, '\n'), '- new hi\n- #hi2');

templates = templates.deleteTemplate('newtemplateName');
assert.strictEqual(templates.toArray().length, 2);
Expand Down