Skip to content

Commit

Permalink
feat: Rewrite suggestions and diagnostics in LG LSP with latest LG AP…
Browse files Browse the repository at this point in the history
…Is (#2208)

* init

* fix importResolver

* fix templates suggestions

* fix return

* fix get all templates method

* fix comments

* fix test cases

* upgrade lgParser related api

* fix

* revert designIds

* revert designIds

* upgrade lg api change

Co-authored-by: zhixzhan <zhixzhan@microsoft.com>
Co-authored-by: Chris Whitten <christopher.whitten@microsoft.com>
  • Loading branch information
3 people authored Mar 24, 2020
1 parent 528a468 commit 8d594d5
Show file tree
Hide file tree
Showing 21 changed files with 309 additions and 284 deletions.
6 changes: 3 additions & 3 deletions Composer/packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@
"@bfc/extensions": "*",
"@bfc/indexers": "*",
"@bfc/shared": "*",
"@microsoft/bf-lu": "4.8.0-preview.111952",
"@emotion/core": "^10.0.7",
"@microsoft/bf-lu": "4.8.0-preview.111952",
"@reach/router": "^1.2.1",
"axios": "^0.18.0",
"botbuilder-lg": "^4.8.0-preview.106823",
"botframework-expressions": "^4.8.0-preview.106476",
"botbuilder-lg": "^4.8.0-preview-109324",
"adaptive-expressions": "^4.8.0-preview-110700",
"format-message": "^6.2.3",
"immer": "^5.2.0",
"jwt-decode": "^2.2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import querystring from 'query-string';
import { StoreContext } from '../../store';
import * as lgUtil from '../../utils/lgUtil';

const { check } = lgIndexer;
const { parse } = lgIndexer;

const lspServerPath = '/lg-language-server';

Expand Down Expand Up @@ -122,13 +122,13 @@ const CodeEditor: React.FC<CodeEditorProps> = props => {
parameters,
body: value,
});
setDiagnostics(check(newContent, id, lgImportresolver));
setDiagnostics(parse(newContent, id, lgImportresolver).diagnostics);
updateLgTemplate(value);
} catch (error) {
setErrorMsg(error.message);
}
} else {
const diags = check(value, id, lgImportresolver);
const diags = parse(value, id, lgImportresolver).diagnostics;
setDiagnostics(diags);
updateLgFile(value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,21 @@ export default function useNotifications(filter?: string) {
});
lgFiles.forEach(lgFile => {
const lgTemplates = get(lgFile, 'templates', []);
lgFile.diagnostics
// only report diagnostics belong to itself.
.filter(({ source, message }) => message.includes(`source: ${source}`))
.map(diagnostic => {
const mappedTemplate = lgTemplates.find(
t =>
get(diagnostic, 'range.start.line') >= get(t, 'range.startLineNumber') &&
get(diagnostic, 'range.end.line') <= get(t, 'range.endLineNumber')
);
const id = lgFile.id;
const location = `${lgFile.id}.lg`;
let lgTemplateName = '';
if (mappedTemplate && mappedTemplate.name.match(LgNamePattern)) {
//should navigate to design page
lgTemplateName = mappedTemplate.name;
}
notifactions.push(new LgNotification(id, lgTemplateName, location, diagnostic, dialogs));
});
lgFile.diagnostics.map(diagnostic => {
const mappedTemplate = lgTemplates.find(
t =>
get(diagnostic, 'range.start.line') >= get(t, 'range.startLineNumber') &&
get(diagnostic, 'range.end.line') <= get(t, 'range.endLineNumber')
);
const id = lgFile.id;
const location = `${lgFile.id}.lg`;
let lgTemplateName = '';
if (mappedTemplate && mappedTemplate.name.match(LgNamePattern)) {
//should navigate to design page
lgTemplateName = mappedTemplate.name;
}
notifactions.push(new LgNotification(id, lgTemplateName, location, diagnostic, dialogs));
});
});
return notifactions;
}, [dialogs, luFiles, lgFiles, projectId]);
Expand Down
6 changes: 4 additions & 2 deletions Composer/packages/client/src/store/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import React, { useReducer, useRef } from 'react';
import once from 'lodash/once';
import { ImportResolverDelegate, ImportResolver } from 'botbuilder-lg';
import { ImportResolverDelegate, LGParser } from 'botbuilder-lg';
import { LgFile, LuFile } from '@bfc/indexers';

import { prepareAxios } from '../utils/auth';
Expand All @@ -17,6 +17,8 @@ import { State, ActionHandlers, BoundActionHandlers, MiddlewareApi, MiddlewareFu
import { undoActionsMiddleware } from './middlewares/undo';
import { ActionType } from './action/types';

const { defaultFileResolver } = LGParser;

const initialState: State = {
dialogs: [],
projectId: '',
Expand Down Expand Up @@ -85,7 +87,7 @@ export const StoreContext = React.createContext<StoreContextValue>({
dispatch: () => {},
actions: {} as ActionHandlers,
resolvers: {
lgImportresolver: ImportResolver.fileResolver,
lgImportresolver: defaultFileResolver,
lgFileResolver: () => undefined,
luFileResolver: () => undefined,
},
Expand Down
22 changes: 4 additions & 18 deletions Composer/packages/client/src/store/reducer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,7 @@ import get from 'lodash/get';
import set from 'lodash/set';
import formatMessage from 'format-message';
import { SensitiveProperties } from '@bfc/shared';
import {
Diagnostic,
DiagnosticSeverity,
LgTemplate,
lgIndexer,
luIndexer,
LuFile,
DialogInfo,
dialogIndexer,
} from '@bfc/indexers';
import { lgIndexer, luIndexer, LuFile, DialogInfo, dialogIndexer } from '@bfc/indexers';
import { ImportResolverDelegate } from 'botbuilder-lg';

import { ActionTypes, FileTypes, BotStatus } from '../../constants';
Expand Down Expand Up @@ -168,15 +159,10 @@ const updateLgTemplate: ReducerFunc = (state, { id, content }) => {
};

state.lgFiles = lgFiles.map(lgFile => {
const { check, parse } = lgIndexer;
const { parse } = lgIndexer;
const { id, content } = lgFile;
const diagnostics = check(content, id, lgImportresolver);
let templates: LgTemplate[] = [];
try {
templates = parse(content, id);
} catch (err) {
diagnostics.push(new Diagnostic(err.message, id, DiagnosticSeverity.Error));
}
const { templates, diagnostics } = parse(content, id, lgImportresolver);

return { ...lgFile, templates, diagnostics, content };
});
return state;
Expand Down
2 changes: 1 addition & 1 deletion Composer/packages/client/src/utils/dialogUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ConceptLabels, DialogGroup, SDKTypes, dialogGroups, seedNewDialog } fro
import get from 'lodash/get';
import set from 'lodash/set';
import cloneDeep from 'lodash/cloneDeep';
import { ExpressionEngine } from 'botframework-expressions';
import { ExpressionEngine } from 'adaptive-expressions';
import { IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
import { DialogInfo } from '@bfc/indexers';

Expand Down
126 changes: 1 addition & 125 deletions Composer/packages/client/src/utils/lgUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,128 +7,4 @@
*
*/

import { LGParser } from 'botbuilder-lg';
import { lgIndexer, LgTemplate } from '@bfc/indexers';

const { parse } = lgIndexer;
export interface Template {
name: string;
parameters?: string[];
body: string;
}

export function increaseNameUtilNotExist(templates: LgTemplate[], name: string): string {
// if duplicate, increse name with Copy1 Copy2 ...

let repeatIndex = 0;
let newName = name;

while (templates.findIndex(item => item.name === newName) !== -1) {
repeatIndex += 1;
newName = name + repeatIndex.toString();
}
return newName;
}

export function updateTemplate(
content: string,
templateName: string,
{ name, parameters = [], body }: LgTemplate
): string {
const resource = LGParser.parse(content);
// add if not exist
if (resource.templates.findIndex(t => t.name === templateName) === -1) {
return resource.addTemplate(name, parameters, body).toString();
} else {
return resource.updateTemplate(templateName, name, parameters, body).toString();
}
}

// if name exist, throw error.
export function addTemplate(content: string, { name, parameters = [], body }: LgTemplate): string {
const resource = LGParser.parse(content);
return resource.addTemplate(name, parameters, body).toString();
}

// if name exist, add it anyway, with name like `${name}1` `${name}2`
export function addTemplateAnyway(
content: string,
{ name = 'TemplateName', parameters = [], body = '-TemplateBody' }: LgTemplate
): string {
const resource = LGParser.parse(content);
const newName = increaseNameUtilNotExist(resource.templates, name);

return resource.addTemplate(newName, parameters, body).toString();
}

// if toTemplateName exist, throw error.
export function copyTemplate(content: string, fromTemplateName: string, toTemplateName: string): string {
const resource = LGParser.parse(content);
const fromTemplate = resource.templates.find(t => t.name === fromTemplateName);
if (!fromTemplate) {
throw new Error('fromTemplateName no exist');
}
const { parameters, body } = fromTemplate;
return resource.addTemplate(toTemplateName, parameters, body).toString();
}

// if toTemplateName exist, add it anyway, with name like `${toTemplateName}1` `${toTemplateName}2`
export function copyTemplateAnyway(content: string, fromTemplateName: string, toTemplateName?: string): string {
const resource = LGParser.parse(content);
const fromTemplate = resource.templates.find(t => t.name === fromTemplateName);
if (!fromTemplate) {
return resource.toString();
}

let newName = toTemplateName;
if (!newName) {
const copyName = `${fromTemplate.name}_Copy`;
newName = increaseNameUtilNotExist(resource.templates, copyName);
}
const { parameters, body } = fromTemplate;
return resource.addTemplate(newName, parameters, body).toString();
}

export function removeTemplate(content: string, templateName: string): string {
const resource = LGParser.parse(content);
return resource.deleteTemplate(templateName).toString();
}

export function removeTemplates(content: string, templateNames: string[]): string {
let resource = LGParser.parse(content);
templateNames.forEach(templateName => {
resource = resource.deleteTemplate(templateName);
});
return resource.toString();
}

export function textFromTemplate(template: LgTemplate): string {
const { name, parameters = [], body } = template;
const textBuilder: string[] = [];
if (name && body !== null && body !== undefined) {
textBuilder.push(`# ${name.trim()}`);
if (parameters.length) {
textBuilder.push(`(${parameters.join(', ')})`);
}
textBuilder.push(`\n${template.body.trim()}`);
}
return textBuilder.join('');
}

export function textFromTemplates(templates: LgTemplate[]): string {
const textBuilder: string[] = [];

templates.forEach(template => {
textBuilder.push(`${textFromTemplate(template)}\n`);
});

return textBuilder.join('');
}

export function checkSingleLgTemplate(template: LgTemplate) {
const content = textFromTemplates([template]);

if (parse(content).length !== 1) {
throw new Error('Not a single template');
}
}
export * from '@bfc/indexers/lib/utils/lgUtil';
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { PrimaryButton, DefaultButton, DirectionalHint } from 'office-ui-fabric-
import debounce from 'lodash/debounce';
import nanoid from 'nanoid';
import { initializeIcons } from '@uifabric/icons';
import { ExpressionEngine } from 'botframework-expressions';
import { ExpressionEngine } from 'adaptive-expressions';
import { seedNewDialog, ShellApi } from '@bfc/shared';
import { LuFile, DialogInfo } from '@bfc/indexers';

Expand Down
2 changes: 1 addition & 1 deletion Composer/packages/extensions/obiformeditor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"@types/react": "16.9.0",
"@types/react-dom": "16.9.0",
"autoprefixer": "^9.5.1",
"botframework-expressions": "^4.8.0-preview.106476",
"adaptive-expressions": "^4.8.0-preview-110700",
"codemirror": "^5.44.0",
"copyfiles": "^2.1.0",
"css-loader": "^2.1.1",
Expand Down
6 changes: 3 additions & 3 deletions Composer/packages/lib/indexers/__tests__/lgIndexer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { lgIndexer } from '../src/lgIndexer';
import { FileInfo } from '../src/type';
import { getBaseName } from '../src/utils/help';

const { parse, index, check } = lgIndexer;
const { parse, index } = lgIndexer;

describe('parse', () => {
it('should parse lg file', () => {
Expand All @@ -14,7 +14,7 @@ describe('parse', () => {
# Greeting
-What's up bro`;
const templates: any = parse(content);
const { templates }: any = parse(content);
expect(templates.length).toEqual(2);
expect(templates[0].name).toEqual('Exit');
expect(templates[1].name).toEqual('Greeting');
Expand All @@ -28,7 +28,7 @@ Thanks for using todo bot.
# Greeting
-What's up bro`;
const diagnostics: any = check(content, 'common');
const { diagnostics }: any = parse(content, 'common');
expect(diagnostics.length).toEqual(1);
});
});
Expand Down
54 changes: 54 additions & 0 deletions Composer/packages/lib/indexers/__tests__/lgUtil.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { LGParser } from 'botbuilder-lg';

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

describe('update lg template', () => {
it('should update lg template', () => {
const content = `# Exit
-Thanks for using todo bot.
# Greeting
-What's up bro`;

const template = { name: 'Exit', parameters: [], body: '-Bye' };
const newContent = updateTemplate(content, 'Exit', template);
const { templates }: any = LGParser.parseText(newContent);
expect(templates.length).toEqual(2);
expect(templates[0].name).toEqual('Exit');
expect(templates[0].body).toEqual('-Bye');
});
});

describe('add lg template', () => {
it('should add lg template', () => {
const content = `# Exit
-Thanks for using todo bot.
# Greeting
-What's up bro`;
const template = { name: 'Hi', parameters: [], body: '-hello' };
const newContent = addTemplate(content, template);
const { templates }: any = LGParser.parseText(newContent);
expect(templates.length).toEqual(3);
expect(templates[0].name).toEqual('Exit');
expect(templates[1].name).toEqual('Greeting');
expect(templates[2].name).toEqual('Hi');
});
});

describe('add lg template', () => {
it('should add lg template', () => {
const content = `# Exit
-Thanks for using todo bot.
# Greeting
-What's up bro`;
const newContent = removeTemplate(content, 'Greeting');
const { templates }: any = LGParser.parseText(newContent);
expect(templates.length).toEqual(1);
expect(templates[0].name).toEqual('Exit');
});
});
4 changes: 2 additions & 2 deletions Composer/packages/lib/indexers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
"dependencies": {
"@bfc/shared": "*",
"@microsoft/bf-lu": "4.8.0-preview.111952",
"botbuilder-lg": "^4.8.0-preview.106823",
"botframework-expressions": "^4.8.0-preview.106476",
"botbuilder-lg": "^4.8.0-preview-109324",
"adaptive-expressions": "^4.8.0-preview-110700",
"lodash": "^4.17.15"
}
}
Loading

0 comments on commit 8d594d5

Please sign in to comment.