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

Fix the issue caused by additional semicolon at the end of some lu definitions #1093

Merged
merged 8 commits into from
Jan 27, 2021
10 changes: 5 additions & 5 deletions packages/lu/src/parser/lufile/parseFileContents.js
Original file line number Diff line number Diff line change
Expand Up @@ -1390,11 +1390,11 @@ const parseAndHandleEntityV2 = function (parsedContent, luResource, log, locale,
case EntityTypeEnum.COMPOSITE:
let candidateChildren = [];
if (entity.CompositeDefinition) {
entity.CompositeDefinition.replace(/[\[\]]/g, '').split(/[,;]/g).map(item => item.trim()).forEach(item => candidateChildren.push(item));
entity.CompositeDefinition.replace(/[\[\]]/g, '').split(/[,;]/g).map(item => item.trim()).filter(s => s).forEach(item => candidateChildren.push(item));
}
if (entity.ListBody) {
entity.ListBody.forEach(line => {
line.trim().substr(1).trim().replace(/[\[\]]/g, '').split(/[,;]/g).map(item => item.trim()).forEach(item => candidateChildren.push(item));
line.trim().substr(1).trim().replace(/[\[\]]/g, '').split(/[,;]/g).map(item => item.trim()).filter(s => s).forEach(item => candidateChildren.push(item));
})
}
handleComposite(parsedContent, entityName,`[${candidateChildren.join(',')}]`, entityRoles, entity.Range, false, entity.Type !== undefined, config);
Expand Down Expand Up @@ -1467,7 +1467,7 @@ const handleNDepthEntity = function(parsedContent, entityName, entityRoles, enti
}
let childEntityName = groupsFound.groups.entityName.replace(/^['"]/g, '').replace(/['"]$/g, '');
let childEntityType = groupsFound.groups.instanceOf.trim();
let childFeatures = groupsFound.groups.features ? groupsFound.groups.features.trim().split(/[,;]/g).map(item => item.trim()) : undefined;
let childFeatures = groupsFound.groups.features ? groupsFound.groups.features.trim().split(/[,;]/g).map(item => item.trim()).filter(s => s) : undefined;

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

let pLEntityExists = parsedContent.LUISJsonStructure.model_features.find(item => item.name == entityName);
Expand Down Expand Up @@ -1902,7 +1902,7 @@ const handleClosedList = function (parsedContent, entityName, listLines, entityR
addNV = true;
}
} else {
line.split(/[,;]/g).forEach(item => {
line.split(/[,;]/g).filter(s => s.trim()).forEach(item => {
item = item.trim();
if (!nvExists || !nvExists.list) {
let errorMsg = `Closed list ${entityName} has synonyms list "${line}" without a normalized value.`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,22 @@ describe('V2 Entity definitions using @ notation', function () {
.then(res => done(res))
.catch(err => done())
});

it('Phrase list definition with semicolon at the end of words is handled correctly', function(done) {
let luFile = `
@phraselist xyz
- x, y, z,
`;

parseFile.parseFile(luFile)
.then(res => {
assert.equal(res.LUISJsonStructure.model_features.length, 1);
assert.equal(res.LUISJsonStructure.model_features[0].name, 'xyz');
assert.equal(res.LUISJsonStructure.model_features[0].words, 'x,y,z');
done();
})
.catch(err => done(err))
});
});

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

it('Basic list child definition with semicolon at the end is handled correctly', function(done) {
let luFile = `
@composite name hasRoles r1, r2 =
- child1;child2;
`;

parseFile.parseFile(luFile)
.then(res => {
assert.equal(res.LUISJsonStructure.composites.length, 1);
assert.equal(res.LUISJsonStructure.composites[0].name, 'name');
assert.equal(res.LUISJsonStructure.composites[0].roles.length, 2);
assert.deepEqual(res.LUISJsonStructure.composites[0].roles, ['r1', 'r2']);
assert.equal(res.LUISJsonStructure.composites[0].children.length, 2);
assert.deepEqual(res.LUISJsonStructure.composites[0].children, ['child1', 'child2']);
done();
})
.catch(err => done(err))
});

it('Definition can be split up in various ways', function(done) {
let luFile = `
@composite name
Expand Down Expand Up @@ -1097,6 +1132,29 @@ describe('V2 Entity definitions using @ notation', function () {
})
.catch(err => done(err))
})

it('Synonymous definition with semicolon at the end is handled correctly', function(done){
let luFile = `
@list x1 =
- a1:
- one;two;
- a2:
-three;four;
`;

parseFile.parseFile(luFile)
.then(res => {
assert.equal(res.LUISJsonStructure.closedLists.length, 1);
assert.equal(res.LUISJsonStructure.closedLists[0].name, 'x1');
assert.equal(res.LUISJsonStructure.closedLists[0].subLists.length, 2);
assert.equal(res.LUISJsonStructure.closedLists[0].subLists[0].canonicalForm, 'a1');
assert.deepEqual(res.LUISJsonStructure.closedLists[0].subLists[0].list, ['one', 'two']);
assert.equal(res.LUISJsonStructure.closedLists[0].subLists[1].canonicalForm, 'a2');
assert.deepEqual(res.LUISJsonStructure.closedLists[0].subLists[1].list, ['three', 'four']);
done();
})
.catch(err => done(err))
});
});

describe('Pattern.Any entity definition', function(){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -816,4 +816,21 @@ describe('V2 NDepth definitions using @ notation', function () {
.catch(err => done())
})

it('nDepth useFeatures can have semicolon at the end of feature list', function(done){
let luFile = `
@ ml nDepth usesFeatures phraselist1
- @ ml nDepth_child2 usesFeatures phraselist1,
@ phraselist phraselist1(interchangeable) =
- who,why,where,what
`;

parseFile.parseFile(luFile)
.then(res => {
assert.equal(res.LUISJsonStructure.entities.length, 1);
assert.equal(res.LUISJsonStructure.entities[0].features[0].featureName, 'phraselist1');
assert.equal(res.LUISJsonStructure.entities[0].children[0].features[0].featureName, 'phraselist1');
done();
})
.catch(err => done(err))
});
});