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

fix: Syntax error when creating a "Send a response" node #3604

Merged
merged 6 commits into from
Jul 9, 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
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ const CodeEditor: React.FC<CodeEditorProps> = (props) => {
setContent(value);
}, [file, templateId, projectId]);

const currentDiagnostics = inlineMode && template ? filterTemplateDiagnostics(diagnostics, template) : diagnostics;
const currentDiagnostics =
inlineMode && file && template ? filterTemplateDiagnostics(file, template.name) : diagnostics;

const editorDidMount: EditorDidMount = (_getValue, lgEditor) => {
setLgEditor(lgEditor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { LuEditor, EditorDidMount } from '@bfc/code-editor';
import get from 'lodash/get';
import debounce from 'lodash/debounce';
import isEmpty from 'lodash/isEmpty';
import { filterTemplateDiagnostics } from '@bfc/indexers';
import { filterSectionDiagnostics } from '@bfc/indexers';
import { RouteComponentProps } from '@reach/router';
import querystring from 'query-string';
import { CodeEditorSettings } from '@bfc/shared';
Expand Down Expand Up @@ -51,7 +51,7 @@ const CodeEditor: React.FC<CodeEditorProps> = (props) => {
setContent(value);
}, [file, sectionId, projectId]);

const currentDiagnostics = inlineMode && intent ? filterTemplateDiagnostics(diagnostics, intent) : diagnostics;
const currentDiagnostics = inlineMode && file && sectionId ? filterSectionDiagnostics(file, sectionId) : diagnostics;

const editorDidMount: EditorDidMount = (_getValue, luEditor) => {
setLuEditor(luEditor);
Expand Down
31 changes: 19 additions & 12 deletions Composer/packages/lib/code-editor/src/LgEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import React, { useState, useEffect } from 'react';
import { listen, MessageConnection } from 'vscode-ws-jsonrpc';
import get from 'lodash/get';
import { MonacoServices } from 'monaco-languageclient';
import { MonacoServices, MonacoLanguageClient } from 'monaco-languageclient';
import { EditorDidMount } from '@monaco-editor/react';

import { registerLGLanguage } from './languages';
Expand Down Expand Up @@ -34,6 +34,7 @@ const defaultLGServer = {
declare global {
interface Window {
monacoServiceInstance: MonacoServices;
monacoLGEditorInstance: MonacoLanguageClient;
}
}

Expand Down Expand Up @@ -63,17 +64,23 @@ export function LgEditor(props: LGLSPEditorProps) {
}

const uri = get(editor.getModel(), 'uri._formatted', '');
const url = createUrl(lgServer);
const webSocket: WebSocket = createWebSocket(url);
listen({
webSocket,
onConnection: (connection: MessageConnection) => {
const languageClient = createLanguageClient('LG Language Client', ['botbuilderlg'], connection);
SendRequestWithRetry(languageClient, 'initializeDocuments', { lgOption, uri });
const disposable = languageClient.start();
connection.onClose(() => disposable.dispose());
},
});

if (!window.monacoLGEditorInstance) {
const url = createUrl(lgServer);
const webSocket: WebSocket = createWebSocket(url);
listen({
webSocket,
onConnection: (connection: MessageConnection) => {
const languageClient = createLanguageClient('LG Language Client', ['botbuilderlg'], connection);
SendRequestWithRetry(languageClient, 'initializeDocuments', { lgOption, uri });
const disposable = languageClient.start();
connection.onClose(() => disposable.dispose());
window.monacoLGEditorInstance = languageClient;
},
});
} else {
SendRequestWithRetry(window.monacoLGEditorInstance, 'initializeDocuments', { lgOption, uri });
}
}, [editor]);

const onInit: OnInit = (monaco) => {
Expand Down
79 changes: 48 additions & 31 deletions Composer/packages/lib/code-editor/src/LuEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import React, { useRef, useState, useEffect } from 'react';
import { listen, MessageConnection } from 'vscode-ws-jsonrpc';
import get from 'lodash/get';
import { MonacoServices } from 'monaco-languageclient';
import { MonacoServices, MonacoLanguageClient } from 'monaco-languageclient';
import { EditorDidMount, Monaco } from '@monaco-editor/react';

import { registerLULanguage } from './languages';
Expand All @@ -31,6 +31,7 @@ const defaultLUServer = {
declare global {
interface Window {
monacoServiceInstance: MonacoServices;
monacoLUEditorInstance: MonacoLanguageClient;
}
}

Expand Down Expand Up @@ -87,37 +88,53 @@ const LuEditor: React.FC<LULSPEditorProps> = (props) => {
}

const uri = get(editor.getModel(), 'uri._formatted', '');
const url = createUrl(luServer);
const webSocket: WebSocket = createWebSocket(url);
listen({
webSocket,
onConnection: (connection: MessageConnection) => {
const languageClient = createLanguageClient('LU Language Client', ['lu'], connection);

const m = monacoRef.current;
if (m) {
// this is the correct way to combine keycodes in Monaco
// eslint-disable-next-line no-bitwise
editor.addCommand(m.KeyMod.Shift | m.KeyCode.Enter, () => {
const position = editor.getPosition();
SendRequestWithRetry(languageClient, 'labelingExperienceRequest', { uri, position });
});
}

SendRequestWithRetry(languageClient, 'initializeDocuments', { luOption, uri });

languageClient.onReady().then(() =>
languageClient.onNotification('addUnlabelUtterance', (result) => {
const edits = result.edits.map((e) => {
return convertEdit(e);

if (!window.monacoLUEditorInstance) {
const url = createUrl(luServer);
const webSocket: WebSocket = createWebSocket(url);
listen({
webSocket,
onConnection: (connection: MessageConnection) => {
const languageClient = createLanguageClient('LU Language Client', ['lu'], connection);

const m = monacoRef.current;
if (m) {
// this is the correct way to combine keycodes in Monaco
// eslint-disable-next-line no-bitwise
editor.addCommand(m.KeyMod.Shift | m.KeyCode.Enter, () => {
const position = editor.getPosition();
SendRequestWithRetry(languageClient, 'labelingExperienceRequest', { uri, position });
});
editor.executeEdits(uri, edits);
})
);
const disposable = languageClient.start();
connection.onClose(() => disposable.dispose());
},
});
}

SendRequestWithRetry(languageClient, 'initializeDocuments', { luOption, uri });

languageClient.onReady().then(() =>
languageClient.onNotification('addUnlabelUtterance', (result) => {
const edits = result.edits.map((e) => {
return convertEdit(e);
});
editor.executeEdits(uri, edits);
})
);
const disposable = languageClient.start();
connection.onClose(() => disposable.dispose());
window.monacoLUEditorInstance = languageClient;
},
});
} else {
const m = monacoRef.current;
const languageClient = window.monacoLUEditorInstance;
if (m) {
// this is the correct way to combine keycodes in Monaco
// eslint-disable-next-line no-bitwise
editor.addCommand(m.KeyMod.Shift | m.KeyCode.Enter, () => {
const position = editor.getPosition();
SendRequestWithRetry(languageClient, 'labelingExperienceRequest', { uri, position });
});
}
SendRequestWithRetry(languageClient, 'initializeDocuments', { luOption, uri });
}
}, [editor]);
const onInit: OnInit = (monaco) => {
registerLULanguage(monaco);
Expand Down
3 changes: 3 additions & 0 deletions Composer/packages/lib/indexers/__tests__/lgIndexer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ describe('parse', () => {
-What's up bro`;
const { templates }: any = parse(content);
expect(templates.length).toEqual(2);
expect(templates[0].range.startLineNumber).toEqual(1);
expect(templates[0].range.endLineNumber).toEqual(3);
expect(templates[0].parameters).toEqual([]);
expect(templates[0].name).toEqual('Exit');
expect(templates[1].name).toEqual('Greeting');
});
Expand Down
30 changes: 26 additions & 4 deletions Composer/packages/lib/indexers/__tests__/lgUtil.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import { Templates } from 'botbuilder-lg';

import { updateTemplate, addTemplate, removeTemplate, extractOptionByKey } from '../src/utils/lgUtil';
import { updateTemplate, addTemplate, checkTemplate, removeTemplate, extractOptionByKey } from '../src/utils/lgUtil';

describe('update lg template', () => {
it('should update lg template', () => {
Expand All @@ -23,7 +23,7 @@ describe('update lg template', () => {

it('should update lg template with error', () => {
const content = `# Exit
-Thanks for using todo bot.\${
-Thanks for using todo bot.\${

# Greeting
-What's up bro`;
Expand Down Expand Up @@ -56,8 +56,8 @@ describe('add lg template', () => {
});
});

describe('add lg template', () => {
it('should add lg template', () => {
describe('remove lg template', () => {
it('should remove lg template', () => {
const content = `# Exit
-Thanks for using todo bot.

Expand All @@ -70,6 +70,28 @@ describe('add lg template', () => {
});
});

describe('check lg template', () => {
it('check a valid template', () => {
const template = {
name: 'Greeting',
body: '-hi',
parameters: [],
};
const diags = checkTemplate(template);
expect(diags).toHaveLength(0);
});

it('check an invalid template', () => {
const template = {
name: 'Greeting',
body: 'hi ${ ',
parameters: [],
};
const diags = checkTemplate(template);
expect(diags).toHaveLength(1);
});
});

describe('extract option by key', () => {
it('should extract optin', () => {
const options = ['@strict = false', '@Namespace = foo', '@Exports = bar, cool'];
Expand Down
4 changes: 2 additions & 2 deletions Composer/packages/lib/indexers/src/lgIndexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ function parse(content: string, id = '', importResolver: ImportResolverDelegate
body: t.body,
parameters: t.parameters,
range: {
startLineNumber: get(t, 'parseTree.start.line', 0),
endLineNumber: get(t, 'parseTree.stop.line', 0),
startLineNumber: get(t, 'sourceRange.parseTree.start.line', 0),
endLineNumber: get(t, 'sourceRange.parseTree.stop.line', 0),
},
};
});
Expand Down
13 changes: 9 additions & 4 deletions Composer/packages/lib/indexers/src/utils/diagnosticUtil.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { LuIntentSection, Diagnostic, DiagnosticSeverity, Range, Position, CodeRange } from '@bfc/shared';
import { Diagnostic, DiagnosticSeverity, Range, Position, CodeRange, LgFile, LuFile } from '@bfc/shared';

export function createSingleMessage(d: Diagnostic): string {
let msg = `${d.message}\n`;
Expand Down Expand Up @@ -47,7 +47,10 @@ export function isDiagnosticWithInRange(diagnostic: Diagnostic, range: CodeRange
return diagnostic.range.start.line >= range.startLineNumber && diagnostic.range.end.line <= range.endLineNumber;
}

export function filterTemplateDiagnostics(diagnostics: Diagnostic[], { range }: { range?: CodeRange }): Diagnostic[] {
export function filterTemplateDiagnostics(file: LgFile, name: string): Diagnostic[] {
const { diagnostics, templates } = file;
const range = templates.find((t) => t.name === name)?.range;

if (!range) return [];
const filteredDiags = diagnostics.filter((d) => {
return d.range && isDiagnosticWithInRange(d, range);
Expand All @@ -65,8 +68,10 @@ export function filterTemplateDiagnostics(diagnostics: Diagnostic[], { range }:
});
}

export function filterSectionDiagnostics(diagnostics: Diagnostic[], section: LuIntentSection): Diagnostic[] {
const { range } = section;
export function filterSectionDiagnostics(file: LuFile, name: string): Diagnostic[] {
const { diagnostics, intents } = file;
const range = intents.find((t) => t.Name === name)?.range;

if (!range) return diagnostics;
const filteredDiags = diagnostics.filter((d) => {
return isDiagnosticWithInRange(d, range);
Expand Down
23 changes: 18 additions & 5 deletions Composer/packages/lib/indexers/src/utils/lgUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*
*/

import { Templates } from 'botbuilder-lg';
import { Templates, Diagnostic as LGDiagnostic } from 'botbuilder-lg';
import { LgTemplate } from '@bfc/shared';

export interface Template {
Expand All @@ -32,14 +32,22 @@ export function increaseNameUtilNotExist(templates: LgTemplate[], name: string):
export function updateTemplate(
content: string,
templateName: string,
{ name, parameters = [], body }: LgTemplate
{ name, parameters, body }: { name?: string; parameters?: string[]; body?: string }
): string {
const resource = Templates.parseText(content);
const originTemplate = resource.toArray().find((t) => t.name === templateName);
// add if not exist
if (resource.toArray().findIndex((t) => t.name === templateName) === -1) {
return resource.addTemplate(name, parameters, body).toString();
if (!originTemplate) {
return resource.addTemplate(templateName, parameters || [], body || '').toString();
} else {
return resource.updateTemplate(templateName, name, parameters, body).toString();
return resource
.updateTemplate(
templateName,
name || originTemplate.name,
parameters || originTemplate.parameters,
body || originTemplate.body
)
.toString();
}
}

Expand Down Expand Up @@ -132,6 +140,11 @@ export function checkSingleLgTemplate(template: LgTemplate) {
}
}

export function checkTemplate(template: LgTemplate): LGDiagnostic[] {
const text = textFromTemplate(template);
return Templates.parseText(text, '').diagnostics;
}

export function extractOptionByKey(nameOfKey: string, options: string[]): string {
let result = '';
for (const option of options) {
Expand Down

This file was deleted.

Loading