Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.

Commit fc25e77

Browse files
authored
Fix the issue caused by additional semicolon at the end of some lu definitions (#1093)
* support output to file for kb:export command * handle splitting semicolon issue at the end of all list item definitions
1 parent 0184ff0 commit fc25e77

File tree

3 files changed

+80
-5
lines changed

3 files changed

+80
-5
lines changed

packages/lu/src/parser/lufile/parseFileContents.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1390,11 +1390,11 @@ const parseAndHandleEntityV2 = function (parsedContent, luResource, log, locale,
13901390
case EntityTypeEnum.COMPOSITE:
13911391
let candidateChildren = [];
13921392
if (entity.CompositeDefinition) {
1393-
entity.CompositeDefinition.replace(/[\[\]]/g, '').split(/[,;]/g).map(item => item.trim()).forEach(item => candidateChildren.push(item));
1393+
entity.CompositeDefinition.replace(/[\[\]]/g, '').split(/[,;]/g).map(item => item.trim()).filter(s => s).forEach(item => candidateChildren.push(item));
13941394
}
13951395
if (entity.ListBody) {
13961396
entity.ListBody.forEach(line => {
1397-
line.trim().substr(1).trim().replace(/[\[\]]/g, '').split(/[,;]/g).map(item => item.trim()).forEach(item => candidateChildren.push(item));
1397+
line.trim().substr(1).trim().replace(/[\[\]]/g, '').split(/[,;]/g).map(item => item.trim()).filter(s => s).forEach(item => candidateChildren.push(item));
13981398
})
13991399
}
14001400
handleComposite(parsedContent, entityName,`[${candidateChildren.join(',')}]`, entityRoles, entity.Range, false, entity.Type !== undefined, config);
@@ -1467,7 +1467,7 @@ const handleNDepthEntity = function(parsedContent, entityName, entityRoles, enti
14671467
}
14681468
let childEntityName = groupsFound.groups.entityName.replace(/^['"]/g, '').replace(/['"]$/g, '');
14691469
let childEntityType = groupsFound.groups.instanceOf.trim();
1470-
let childFeatures = groupsFound.groups.features ? groupsFound.groups.features.trim().split(/[,;]/g).map(item => item.trim()) : undefined;
1470+
let childFeatures = groupsFound.groups.features ? groupsFound.groups.features.trim().split(/[,;]/g).map(item => item.trim()).filter(s => s) : undefined;
14711471

14721472
// Get current tab level
14731473
let tabLevel = Math.ceil(groupsFound.groups.leadingSpaces !== undefined ? groupsFound.groups.leadingSpaces.length / SPACEASTABS : 0) || (groupsFound.groups.leadingTabs !== undefined ? groupsFound.groups.leadingTabs.length : 0);
@@ -1682,7 +1682,7 @@ const handlePhraseList = function(parsedContent, entityName, entityType, entityR
16821682
// add this to phraseList if it doesnt exist
16831683
let pLValues = [];
16841684
for (const phraseListValues of valuesList) {
1685-
phraseListValues.split(/[,;]/g).map(item => item.trim()).forEach(item => pLValues.push(item));
1685+
phraseListValues.split(/[,;]/g).map(item => item.trim()).filter(s => s).forEach(item => pLValues.push(item));
16861686
}
16871687

16881688
let pLEntityExists = parsedContent.LUISJsonStructure.model_features.find(item => item.name == entityName);
@@ -1902,7 +1902,7 @@ const handleClosedList = function (parsedContent, entityName, listLines, entityR
19021902
addNV = true;
19031903
}
19041904
} else {
1905-
line.split(/[,;]/g).forEach(item => {
1905+
line.split(/[,;]/g).filter(s => s.trim()).forEach(item => {
19061906
item = item.trim();
19071907
if (!nvExists || !nvExists.list) {
19081908
let errorMsg = `Closed list ${entityName} has synonyms list "${line}" without a normalized value.`;

packages/lu/test/parser/lufile/parseFileContents.NewEntityDefinition.test.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,22 @@ describe('V2 Entity definitions using @ notation', function () {
716716
.then(res => done(res))
717717
.catch(err => done())
718718
});
719+
720+
it('Phrase list definition with semicolon at the end of words is handled correctly', function(done) {
721+
let luFile = `
722+
@phraselist xyz
723+
- x, y, z,
724+
`;
725+
726+
parseFile.parseFile(luFile)
727+
.then(res => {
728+
assert.equal(res.LUISJsonStructure.model_features.length, 1);
729+
assert.equal(res.LUISJsonStructure.model_features[0].name, 'xyz');
730+
assert.equal(res.LUISJsonStructure.model_features[0].words, 'x,y,z');
731+
done();
732+
})
733+
.catch(err => done(err))
734+
});
719735
});
720736

721737
describe('Prebuilt entity types', function(done) {
@@ -927,6 +943,25 @@ describe('V2 Entity definitions using @ notation', function () {
927943
.catch(err => done(err))
928944
});
929945

946+
it('Basic list child definition with semicolon at the end is handled correctly', function(done) {
947+
let luFile = `
948+
@composite name hasRoles r1, r2 =
949+
- child1;child2;
950+
`;
951+
952+
parseFile.parseFile(luFile)
953+
.then(res => {
954+
assert.equal(res.LUISJsonStructure.composites.length, 1);
955+
assert.equal(res.LUISJsonStructure.composites[0].name, 'name');
956+
assert.equal(res.LUISJsonStructure.composites[0].roles.length, 2);
957+
assert.deepEqual(res.LUISJsonStructure.composites[0].roles, ['r1', 'r2']);
958+
assert.equal(res.LUISJsonStructure.composites[0].children.length, 2);
959+
assert.deepEqual(res.LUISJsonStructure.composites[0].children, ['child1', 'child2']);
960+
done();
961+
})
962+
.catch(err => done(err))
963+
});
964+
930965
it('Definition can be split up in various ways', function(done) {
931966
let luFile = `
932967
@composite name
@@ -1097,6 +1132,29 @@ describe('V2 Entity definitions using @ notation', function () {
10971132
})
10981133
.catch(err => done(err))
10991134
})
1135+
1136+
it('Synonymous definition with semicolon at the end is handled correctly', function(done){
1137+
let luFile = `
1138+
@list x1 =
1139+
- a1:
1140+
- one;two;
1141+
- a2:
1142+
-three;four;
1143+
`;
1144+
1145+
parseFile.parseFile(luFile)
1146+
.then(res => {
1147+
assert.equal(res.LUISJsonStructure.closedLists.length, 1);
1148+
assert.equal(res.LUISJsonStructure.closedLists[0].name, 'x1');
1149+
assert.equal(res.LUISJsonStructure.closedLists[0].subLists.length, 2);
1150+
assert.equal(res.LUISJsonStructure.closedLists[0].subLists[0].canonicalForm, 'a1');
1151+
assert.deepEqual(res.LUISJsonStructure.closedLists[0].subLists[0].list, ['one', 'two']);
1152+
assert.equal(res.LUISJsonStructure.closedLists[0].subLists[1].canonicalForm, 'a2');
1153+
assert.deepEqual(res.LUISJsonStructure.closedLists[0].subLists[1].list, ['three', 'four']);
1154+
done();
1155+
})
1156+
.catch(err => done(err))
1157+
});
11001158
});
11011159

11021160
describe('Pattern.Any entity definition', function(){

packages/lu/test/parser/lufile/parseFileContents.nDepthEntity.test.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,4 +816,21 @@ describe('V2 NDepth definitions using @ notation', function () {
816816
.catch(err => done())
817817
})
818818

819+
it('nDepth useFeatures can have semicolon at the end of feature list', function(done){
820+
let luFile = `
821+
@ ml nDepth usesFeatures phraselist1
822+
- @ ml nDepth_child2 usesFeatures phraselist1,
823+
@ phraselist phraselist1(interchangeable) =
824+
- who,why,where,what
825+
`;
826+
827+
parseFile.parseFile(luFile)
828+
.then(res => {
829+
assert.equal(res.LUISJsonStructure.entities.length, 1);
830+
assert.equal(res.LUISJsonStructure.entities[0].features[0].featureName, 'phraselist1');
831+
assert.equal(res.LUISJsonStructure.entities[0].children[0].features[0].featureName, 'phraselist1');
832+
done();
833+
})
834+
.catch(err => done(err))
835+
});
819836
});

0 commit comments

Comments
 (0)