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: project tree show incorrect imports #5361

Merged
merged 14 commits into from
Jan 8, 2021
Merged
Show file tree
Hide file tree
Changes from 3 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 @@ -42,6 +42,7 @@ const lgFiles = [
content: `\r\n# Hello\r\n-hi`,
templates: [{ name: 'Hello', body: '-hi', parameters: [] }],
diagnostics: [],
imports: [],
allTemplates: [{ name: 'Hello', body: '-hi', parameters: [] }],
},
] as LgFile[];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { lgUtil } from '@bfc/indexers';

import { getBaseName } from '../../../utils/fileUtil';
import { getLanguageFileImports } from '../dialogImports';

Expand Down Expand Up @@ -37,7 +39,14 @@ const files = [

describe('dialogImports selectors', () => {
it('should follow all imports and list all unique imports', () => {
const getFile = (id) => files.find((f) => getBaseName(f.id) === id) as { id: string; content: string };
const getFile = (id) => {
const file = files.find((f) => getBaseName(f.id) === id);
if (file) {
return lgUtil.parse(file.id, file.content, []);
} else {
throw new Error(`file ${id} not found`);
}
};

const fileImports = getLanguageFileImports('name1', getFile);
expect(fileImports).toEqual([
Expand Down
37 changes: 11 additions & 26 deletions Composer/packages/client/src/recoilModel/selectors/dialogImports.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,15 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { LanguageFileImport, LgFile, LuFile } from '@bfc/shared';
import { LanguageFileImport, LgFile, LuFile, QnAFile } from '@bfc/shared';
import uniqBy from 'lodash/uniqBy';
import { selectorFamily } from 'recoil';

import { getBaseName, getFileName } from '../../utils/fileUtil';
import { getBaseName } from '../../utils/fileUtil';
import { localeState, lgFilesState, luFilesState } from '../atoms';

// eslint-disable-next-line security/detect-unsafe-regex
const importRegex = /\[(?<id>.*?)]\((?<importPath>.*?)(?="|\))(?<optionalpart>".*")?\)/g;

const getImportsHelper = (content: string): LanguageFileImport[] => {
const lines = content.split(/\r?\n/g).filter((l) => !!l) ?? [];

return (lines
.map((l) => {
importRegex.lastIndex = 0;
return importRegex.exec(l) as RegExpExecArray;
})
.filter(Boolean) as RegExpExecArray[]).map((regExecArr) => {
const importPath = regExecArr.groups?.importPath ?? '';

return {
displayName: regExecArr.groups?.id ?? '',
importPath,
id: getBaseName(getFileName(importPath)),
};
});
};

// Finds all the file imports starting from a given dialog file.
export const getLanguageFileImports = <T extends { id: string; content: string }>(
export const getLanguageFileImports = <T extends LgFile | LuFile | QnAFile>(
rootDialogId: string,
getFile: (fileId: string) => T
): LanguageFileImport[] => {
Expand All @@ -55,7 +33,14 @@ export const getLanguageFileImports = <T extends { id: string; content: string }
console.warn(`Could not find language import file ${currentId}`);
continue;
}
const currentImports = getImportsHelper(file.content);
const currentImports = file.imports.map((item) => {
return {
displayName: item.description,
importPath: item.path,
id: getBaseName(item.id),
};
});

visitedIds.push(currentId);
imports.push(...currentImports);
const newIds = currentImports.map((ci) => getBaseName(ci.id));
Expand Down
18 changes: 9 additions & 9 deletions Composer/packages/lib/indexers/__tests__/lgIndexer.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { FileInfo } from '@bfc/shared';
import { FileInfo, lgImportResolverGenerator, ResolverResource } from '@bfc/shared';
import { LGResource } from 'botbuilder-lg';

import { lgIndexer } from '../src/lgIndexer';
import { getBaseName } from '../src/utils/help';
Expand Down Expand Up @@ -54,25 +55,24 @@ describe('index', () => {
lastModified: '',
};

const files = {
common: {
const files = [
{
id: 'common',
content: `# Greeting
-What's up bro`,
},
};
] as ResolverResource[];

const importResolver = (_source: string, _id: string) => {
const id = getBaseName(_id.split('/').pop() || '', '.lg');
return files[id];
};
const importresolver = lgImportResolverGenerator(files, '.lg');

it('should index lg file with [import]', () => {
const { id, templates, diagnostics }: any = index([file], importResolver)[0];
const { id, templates, diagnostics, imports }: any = index([file], importresolver)[0];
expect(id).toEqual('test');
expect(templates.length).toEqual(2);
expect(diagnostics.length).toEqual(0);
expect(templates[0].name).toEqual('Exit');
expect(templates[1].name).toEqual('Hi');
expect(imports.length).toEqual(1);
expect(imports[0]).toEqual({ id: 'common.lg', path: '../common/common.lg', description: 'import' });
});
});
19 changes: 16 additions & 3 deletions Composer/packages/lib/indexers/__tests__/luIndexer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe('parse', () => {
@ simple fooName

`;
const { intents, diagnostics }: any = parse(content);
const { intents, diagnostics }: any = parse(content, '', {});
expect(diagnostics.length).toEqual(0);
expect(intents.length).toEqual(4);
expect(intents[0].Name).toEqual('CheckTodo');
Expand All @@ -44,6 +44,19 @@ describe('parse', () => {
expect(intents[0].Children[0].Entities[0]).toEqual('todoTitle');
});

it('should parse LU file with import', () => {
const content = `[import](greating.lu)
[import](../common/aks.lu)
`;

const result = parse(content, '', {});
expect(result.imports.length).toEqual(2);
expect(result.imports[0]).toEqual({ id: 'greating.lu', path: 'greating.lu', description: 'import' });
expect(result.imports[1]).toEqual({ id: 'aks.lu', path: '../common/aks.lu', description: 'import' });
expect(result.empty).toEqual(false);
expect(result.intents.length).toEqual(0);
});

it('should parse lu file with diagnostic', () => {
const content = `# Greeting
hi
Expand All @@ -52,7 +65,7 @@ hi
@ simple friendsName

`;
const { intents, diagnostics }: any = parse(content);
const { intents, diagnostics }: any = parse(content, '', {});
expect(intents.length).toEqual(1);
expect(diagnostics.length).toEqual(1);
expect(diagnostics[0].range.start.line).toEqual(2);
Expand Down Expand Up @@ -80,7 +93,7 @@ describe('index', () => {
};

it('should index lu file', () => {
const { id, intents, diagnostics }: any = index([file])[0];
const { id, intents, diagnostics }: any = index([file], {})[0];
expect(id).toEqual('test');
expect(diagnostics.length).toEqual(0);
expect(intents.length).toEqual(1);
Expand Down
8 changes: 6 additions & 2 deletions Composer/packages/lib/indexers/__tests__/qnaIndexer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,12 @@ describe('parse', () => {

const result = parse('a.qna', content);
expect(result.imports.length).toEqual(2);
expect(result.imports[0]).toEqual({ id: 'windows-guide.source.qna', path: 'windows-guide.source.qna' });
expect(result.imports[1]).toEqual({ id: 'aks.qna', path: '../common/aks.qna' });
expect(result.imports[0]).toEqual({
id: 'windows-guide.source.qna',
path: 'windows-guide.source.qna',
description: 'import',
});
expect(result.imports[1]).toEqual({ id: 'aks.qna', path: '../common/aks.qna', description: 'import' });
expect(result.empty).toEqual(false);
expect(result.qnaSections.length).toEqual(0);
});
Expand Down
7 changes: 7 additions & 0 deletions Composer/packages/lib/indexers/__tests__/qnaUtil.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,10 +292,12 @@ ${content1}
expect(imports).toEqual([
{
id: 'help.qna',
description: 'import',
path: '../common/help.qna',
},
{
id: 'windows.source.qna',
description: 'import',
path: 'windows.source.qna',
},
]);
Expand All @@ -311,14 +313,17 @@ ${content1}
{
id: 'chitchat.qna',
path: 'chitchat.qna',
description: 'import',
},
{
id: 'help.qna',
path: '../common/help.qna',
description: 'import',
},
{
id: 'windows.source.qna',
path: 'windows.source.qna',
description: 'import',
},
]);
});
Expand All @@ -334,6 +339,7 @@ ${content1}
{
id: 'chitchat.qna',
path: 'chitchat.qna',
description: 'import',
},
]);
});
Expand All @@ -348,6 +354,7 @@ ${content1}
{
id: 'help.qna',
path: '../common/help.qna',
description: 'import',
},
]);
});
Expand Down
11 changes: 10 additions & 1 deletion Composer/packages/lib/indexers/src/utils/lgUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { SourceRange } from 'botbuilder-lg/lib/sourceRange';

import { lgIndexer } from '../lgIndexer';

import { getFileName } from './help';

// NOTE: LGDiagnostic is defined in PascalCase which should be corrected
function convertLGDiagnostic(d: LGDiagnostic, source: string): Diagnostic {
const result = new Diagnostic(d.message, source, d.severity);
Expand Down Expand Up @@ -57,8 +59,15 @@ export function convertTemplatesToLgFile(id = '', content: string, parseResult:

const templates = templateToLgTemplate(parseResult.toArray());
const allTemplates = templateToLgTemplate(parseResult.allTemplates);
const imports = parseResult.imports.map((item) => {
return {
id: getFileName(item.id),
path: item.id,
description: item.description,
};
});

return { id, content, templates, allTemplates, diagnostics, options: parseResult.options, parseResult };
return { id, content, templates, allTemplates, diagnostics, imports, options: parseResult.options, parseResult };
}

export function increaseNameUtilNotExist(templates: LgTemplate[], name: string): string {
Expand Down
14 changes: 13 additions & 1 deletion Composer/packages/lib/indexers/src/utils/luUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ import {
} from '@bfc/shared';
import formatMessage from 'format-message';

import { buildNewlineText, splitNewlineText } from './help';
import { buildNewlineText, getFileName, splitNewlineText } from './help';
import { SectionTypes } from './qnaUtil';

const { luParser, sectionOperator } = sectionHandler;
const { parseFile, validateResource } = BFLUParser;
Expand Down Expand Up @@ -104,13 +105,24 @@ export function convertLuParseResultToLuFile(id: string, resource, luFeatures: I
convertLuDiagnostic(e, id)
) as Diagnostic[];

const imports = Sections.filter(({ SectionType }) => SectionType === SectionTypes.ImportSection).map(
({ Path, Description }) => {
return {
id: getFileName(Path),
description: Description,
path: Path,
};
}
);

const diagnostics = syntaxDiagnostics.concat(semanticDiagnostics);
return {
id,
content: Content,
empty: !Sections.length,
intents,
diagnostics,
imports,
resource: { Sections, Errors, Content },
};
}
Expand Down
17 changes: 10 additions & 7 deletions Composer/packages/lib/indexers/src/utils/qnaUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const { luParser, sectionOperator } = sectionHandler;

const NEWLINE = '\n';

enum SectionTypes {
export enum SectionTypes {
QnASection = 'qnaSection',
ImportSection = 'importSection',
LUModelInfo = 'modelInfoSection',
Expand Down Expand Up @@ -115,12 +115,15 @@ export function convertQnAParseResultToQnAFile(id = '', resource: LuParseResourc
};
});

const imports = Sections.filter(({ SectionType }) => SectionType === SectionTypes.ImportSection).map(({ Path }) => {
return {
id: getFileName(Path),
path: Path,
};
});
const imports = Sections.filter(({ SectionType }) => SectionType === SectionTypes.ImportSection).map(
({ Path, Description }) => {
return {
id: getFileName(Path),
description: Description,
path: Path,
};
}
);

const optionRegExp = new RegExp(/@source\.(\w+)\s*=\s*(.*)/);
const options: { id: string; name: string; value: string }[] = [];
Expand Down
4 changes: 3 additions & 1 deletion Composer/packages/types/src/indexers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export type LuFile = {
intents: LuIntentSection[];
empty: boolean;
resource: LuParseResource;
imports: { id: string; path: string; description: string }[];
[key: string]: any;
};

Expand All @@ -136,7 +137,7 @@ export type QnAFile = {
content: string;
diagnostics: IDiagnostic[];
qnaSections: QnASection[];
imports: { id: string; path: string }[];
imports: { id: string; path: string; description: string }[];
options: { id: string; name: string; value: string }[];
empty: boolean;
resource: LuParseResource;
Expand Down Expand Up @@ -178,6 +179,7 @@ export type LgFile = {
diagnostics: IDiagnostic[];
templates: LgTemplate[];
allTemplates: LgTemplate[];
imports: { id: string; path: string; description: string }[];
options?: string[];
parseResult?: any;
};
Expand Down