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

Commit 05d0b13

Browse files
munozemiliofeich-msChris McConnell
authored
Cherry pick from main (#1127)
* fix import bug (#1124) * Add support for verifying $policies. (#1126) * Add support for verifying $policies. * Remove unneed package reference. Co-authored-by: Chris McConnell <chrimc> Co-authored-by: Emilio Munoz <[email protected]> Co-authored-by: Fei Chen <[email protected]> Co-authored-by: Chris McConnell <[email protected]>
1 parent 8fcf25e commit 05d0b13

File tree

13 files changed

+225
-20
lines changed

13 files changed

+225
-20
lines changed

common/config/rush/pnpm-lock.yaml

Lines changed: 11 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/dialog/src/library/schemaMerger.ts

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ export class SchemaMerger {
623623
this.expandInterfaces()
624624
this.addComponentProperties()
625625
this.sortImplementations()
626+
this.validateAndExpandPolicies()
626627
const oneOf = Object.keys(this.definitions)
627628
.filter(kind => !this.isInterface(kind) && this.definitions[kind].$role)
628629
.sort()
@@ -889,6 +890,36 @@ export class SchemaMerger {
889890
return imports
890891
}
891892

893+
// Return all recursive extensions of a kind including the original kind
894+
private allExtensions(kind: string): string[] {
895+
let exts: string[] = [kind]
896+
for (const [dkind, definition] of Object.entries(this.definitions)) {
897+
for (const extension of this.roles(definition, 'extends')) {
898+
if (extension === kind) {
899+
exts = [...exts, ...this.allExtensions(dkind)]
900+
}
901+
}
902+
}
903+
return exts
904+
}
905+
906+
// Ensure kinds in policies exist and we expand to any extensions
907+
private validateAndExpandPolicies(): void {
908+
walkJSON(this.definitions, (val, _obj, path) => {
909+
if (val.$policies?.requiresKind) {
910+
let expanded: string[] = []
911+
for(const kind of val.$policies.requiresKind) {
912+
if (!this.definitions[kind]) {
913+
this.genericError(`Error ${path} has non-existent $kind ${kind}`)
914+
}
915+
expanded = [...expanded, ...this.allExtensions(kind)]
916+
}
917+
val.$policies.requiresKind = expanded
918+
}
919+
return false
920+
})
921+
}
922+
892923
// Given schema properties object and ui schema properties object, check to ensure
893924
// each ui schema property exists in schema
894925
private validateProperties(path: string, schema: any, uiProps: object): void {
@@ -1777,7 +1808,7 @@ export class SchemaMerger {
17771808
const ref = `#/definitions/${name}${pointer}`
17781809
const definition: any = ptr.get(schema, ref)
17791810
if (!definition) {
1780-
this.refError(elt.$ref, ref)
1811+
this.genericError(`Error could not bundle ${elt.$ref} into ${ref}`)
17811812
} else if (!elt.$bundled) {
17821813
elt.$ref = ref
17831814
elt.$bundled = true
@@ -2054,9 +2085,9 @@ export class SchemaMerger {
20542085
this.failed = true
20552086
}
20562087

2057-
// Missing $ref
2058-
private refError(original: string, modified: string): void {
2059-
this.error(`Error could not bundle ${original} into ${modified}`)
2088+
// Generic error message
2089+
private genericError(msg: string) {
2090+
this.error(msg)
20602091
this.failed = true
20612092
}
20622093
}

packages/dialog/test/commands/dialog/merge.test.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// tslint:disable:no-console
66
// tslint:disable:no-object-literal-type-assertion
77

8-
import { assert } from 'chai'
8+
import {assert} from 'chai'
99
import * as fs from 'fs-extra'
1010
import 'mocha'
1111
import * as os from 'os'
@@ -128,7 +128,7 @@ function checkMerged(merged: merger.Imports | undefined, adds: number, conflicts
128128

129129
describe('dialog:merge', async () => {
130130
beforeEach(async () => {
131-
// If you want to regenerate the oracle *.schema files, run schemas/makeschemas.cmd
131+
// If you want to regenerate the oracle *.schema files, run makeOracles.cmd
132132
await fs.remove(tempDir)
133133
await fs.mkdirp(tempDir)
134134
process.chdir(srcDir)
@@ -207,6 +207,14 @@ describe('dialog:merge', async () => {
207207
assert(countMatches('no implementations', lines) === 1, 'Did not detect missing implementations')
208208
})
209209

210+
it('missing policy kind', async () => {
211+
console.log('\nStart missing policy kind')
212+
let [merged, lines] = await merge(['schemas/*.schema', 'schemas/badSchemas/missingPolicyKind.schema'])
213+
assert(!merged, 'Merging should have failed')
214+
assert(countMatches(/error|warning/i, lines) === 1, 'Wrong number of errors or warnings')
215+
assert(countMatches('non-existent', lines) === 1, 'Did not detect missing $kind')
216+
})
217+
210218
it('csproj', async () => {
211219
console.log('\nStart csproj')
212220
let [merged, lines] = await merge(['projects/project3/project3.csproj'], 'project3.schema', true)

packages/dialog/test/commands/dialog/oracles/app.schema

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
{
88
"$ref": "#/definitions/Recognizer"
99
},
10+
{
11+
"$ref": "#/definitions/policyLevel2"
12+
},
1013
{
1114
"$ref": "#/definitions/prompt"
1215
},
@@ -288,6 +291,109 @@
288291
}
289292
]
290293
},
294+
"policyExpandKind": {
295+
"$policies": {
296+
"requiresKind": [
297+
"policyLevel1",
298+
"policyLevel2"
299+
]
300+
},
301+
"type": "object",
302+
"required": [
303+
"$kind"
304+
],
305+
"additionalProperties": false,
306+
"patternProperties": {
307+
"^\\$": {
308+
"title": "Tooling property",
309+
"description": "Open ended property for tooling."
310+
}
311+
},
312+
"properties": {
313+
"$kind": {
314+
"title": "Kind of dialog object",
315+
"description": "Defines the valid properties for the component you are configuring (from a dialog .schema file)",
316+
"type": "string",
317+
"pattern": "^[a-zA-Z][a-zA-Z0-9.]*$",
318+
"const": "policyExpandKind"
319+
},
320+
"$designer": {
321+
"title": "Designer information",
322+
"type": "object",
323+
"description": "Extra information for the Bot Framework Composer."
324+
}
325+
}
326+
},
327+
"policyLevel1": {
328+
"type": "object",
329+
"required": [
330+
"$kind"
331+
],
332+
"additionalProperties": false,
333+
"patternProperties": {
334+
"^\\$": {
335+
"title": "Tooling property",
336+
"description": "Open ended property for tooling."
337+
}
338+
},
339+
"properties": {
340+
"level1": {
341+
"title": "level1",
342+
"description": "level1",
343+
"type": "string"
344+
},
345+
"$kind": {
346+
"title": "Kind of dialog object",
347+
"description": "Defines the valid properties for the component you are configuring (from a dialog .schema file)",
348+
"type": "string",
349+
"pattern": "^[a-zA-Z][a-zA-Z0-9.]*$",
350+
"const": "policyLevel1"
351+
},
352+
"$designer": {
353+
"title": "Designer information",
354+
"type": "object",
355+
"description": "Extra information for the Bot Framework Composer."
356+
}
357+
}
358+
},
359+
"policyLevel2": {
360+
"$role": "extends(policyLevel1)",
361+
"type": "object",
362+
"required": [
363+
"$kind"
364+
],
365+
"additionalProperties": false,
366+
"patternProperties": {
367+
"^\\$": {
368+
"title": "Tooling property",
369+
"description": "Open ended property for tooling."
370+
}
371+
},
372+
"properties": {
373+
"level2": {
374+
"title": "level2",
375+
"description": "level2",
376+
"type": "string"
377+
},
378+
"level1": {
379+
"title": "level1",
380+
"description": "level1",
381+
"type": "string"
382+
},
383+
"$kind": {
384+
"title": "Kind of dialog object",
385+
"description": "Defines the valid properties for the component you are configuring (from a dialog .schema file)",
386+
"type": "string",
387+
"pattern": "^[a-zA-Z][a-zA-Z0-9.]*$",
388+
"const": "policyLevel2"
389+
},
390+
"$designer": {
391+
"title": "Designer information",
392+
"type": "object",
393+
"description": "Extra information for the Bot Framework Composer."
394+
}
395+
}
396+
},
291397
"prompt": {
292398
"$role": "extends(basePrompt)",
293399
"required": [
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"$schema": "https://schemas.botframework.com/schemas/component/v1.0/component.schema",
3+
"$policies": {
4+
"requiresKind": [
5+
"missingKind"
6+
]
7+
}
8+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"$schema": "https://schemas.botframework.com/schemas/component/v1.0/component.schema",
3+
"$policies": {
4+
"requiresKind": ["policyLevel1"]
5+
}
6+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"$schema": "https://schemas.botframework.com/schemas/component/v1.0/component.schema",
3+
"type": "object",
4+
"properties": {
5+
"level1": {
6+
"title": "level1",
7+
"description": "level1",
8+
"type": "string"
9+
}
10+
}
11+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"$schema": "https://schemas.botframework.com/schemas/component/v1.0/component.schema",
3+
"$role": "extends(policyLevel1)",
4+
"type": "object",
5+
"properties": {
6+
"level2": {
7+
"title": "level2",
8+
"description": "level2",
9+
"type": "string"
10+
}
11+
}
12+
}

packages/dialog/test/commands/dialog/verify.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ describe('dialog:verify', () => {
3232
expect(ctx.stderr.match(/DLG005/)!.length == 6, 'Wrong number of unsued ids')
3333
expect(ctx.stdout).to.contain('4 files')
3434
expect(ctx.stderr)
35-
.to.contain('Warnings: 2')
36-
.to.contain('Errors: 12')
35+
.to.contain('Warnings: 2', 'Wrong number of warnings')
36+
.to.contain('Errors: 13', 'Wrong number of errors')
3737
})
3838
})

packages/lu/src/parser/lu/luMerger.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,8 @@ const buildLuJsonObject = async function(luObjArray, log, luis_culture, luSearch
392392
continue
393393
}
394394

395+
// Set includeInCollate in addtionalFilesToParse to be false if current parsedContent's includeInCollate is false
396+
parsedContent.additionalFilesToParse.forEach(addtionFileToParse => addtionFileToParse.includeInCollate = luOb.includeInCollate ? addtionFileToParse.includeInCollate : luOb.includeInCollate)
395397
let foundLuFiles = await luSearchFn(luOb.id, parsedContent.additionalFilesToParse)
396398
for( let i = 0; i < foundLuFiles.length; i++){
397399
if (parsedFiles.includes(foundLuFiles[i].id)) {

0 commit comments

Comments
 (0)