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

Commit bc3e4b2

Browse files
Chris McConnellmunozemilio
andauthored
Switch to interface/implements in dialog:merge. (#621)
Co-authored-by: Emilio Munoz <[email protected]>
1 parent a8d711b commit bc3e4b2

File tree

11 files changed

+50
-72
lines changed

11 files changed

+50
-72
lines changed

libraries/Microsoft.Bot.Builder.Dialogs.Adaptive/Schemas/Microsoft.AdaptiveDialog.schema

Whitespace-only changes.

packages/dialog/src/commands/dialog/merge.ts

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ export default class DialogMerge extends Command {
146146
}
147147
let filename = schemaPath.split(/[\\\/]/).pop() as string
148148
let kind = filename.substr(0, filename.lastIndexOf('.'))
149-
if (!schema.type && !this.isUnion(schema)) {
149+
if (!schema.type && !this.isInterface(schema)) {
150150
schema.type = 'object'
151151
}
152152
definitions[kind] = schema
@@ -157,7 +157,7 @@ export default class DialogMerge extends Command {
157157
this.addKindTitles(definitions)
158158
this.expandKinds(definitions)
159159
this.addStandardProperties(definitions, metaSchema)
160-
this.sortUnions(definitions)
160+
this.sortImplementations(definitions)
161161
let finalDefinitions: any = {}
162162
for (let key of Object.keys(definitions).sort()) {
163163
finalDefinitions[key] = definitions[key]
@@ -169,7 +169,7 @@ export default class DialogMerge extends Command {
169169
title: 'Component kinds',
170170
description: 'These are all of the kinds that can be created by the loader.',
171171
oneOf: Object.keys(definitions)
172-
.filter(schemaName => !this.isUnion(definitions[schemaName]))
172+
.filter(schemaName => !this.isInterface(definitions[schemaName]))
173173
.sort()
174174
.map(schemaName => {
175175
return {
@@ -360,7 +360,7 @@ export default class DialogMerge extends Command {
360360
}
361361

362362
processRole(role: string, elt: any, kind: string, definitions: any, key?: string): void {
363-
const prefix = 'union('
363+
const prefix = 'implements('
364364
if (role === 'expression') {
365365
const reserved = ['title', 'description', 'examples', '$role']
366366
if (elt.kind) {
@@ -400,29 +400,29 @@ export default class DialogMerge extends Command {
400400
choices.push({ type: 'string', title: 'Expression' })
401401
}
402402
}
403-
} else if (role === 'union') {
403+
} else if (role === 'interface') {
404404
if (key) {
405-
this.error(`${this.currentFile}:error: union $role can only be defined at the top of the schema definition.`)
405+
this.error(`${this.currentFile}:error: interface $role can only be defined at the top of the schema definition.`)
406406
}
407407
} else if (role.startsWith(prefix) && role.endsWith(')')) {
408-
let union = role.substring(prefix.length, role.length - 1)
409-
if (!definitions[union]) {
410-
this.error(`${this.currentFile}:error: union ${union} is not defined.`)
411-
} else if (!this.isUnion(definitions[union])) {
412-
this.error(`${this.currentFile}:error: is missing $role of union.`)
408+
let interfaceName = role.substring(prefix.length, role.length - 1)
409+
if (!definitions[interfaceName]) {
410+
this.error(`${this.currentFile}:error: interface ${interfaceName} is not defined.`)
411+
} else if (!this.isInterface(definitions[interfaceName])) {
412+
this.error(`${this.currentFile}:error: is missing $role of interface.`)
413413
} else {
414414
let definition = definitions[kind]
415-
let unionDefinition = definitions[union]
416-
if (!unionDefinition.oneOf) {
417-
unionDefinition.oneOf = [
415+
let interfaceDefinition = definitions[interfaceName]
416+
if (!interfaceDefinition.oneOf) {
417+
interfaceDefinition.oneOf = [
418418
{
419419
type: 'string',
420-
title: `Reference to ${union}`,
421-
description: `Reference to ${union} .dialog file.`
420+
title: `Reference to ${interfaceName}`,
421+
description: `Reference to ${interfaceName} .dialog file.`
422422
}
423423
]
424424
}
425-
unionDefinition.oneOf.push({
425+
interfaceDefinition.oneOf.push({
426426
title: kind,
427427
description: definition.description || '',
428428
$ref: `#/definitions/${kind}`
@@ -478,7 +478,7 @@ export default class DialogMerge extends Command {
478478
addStandardProperties(definitions: any, dialogSchema: any): void {
479479
for (let kind in definitions) {
480480
let definition = definitions[kind]
481-
if (!this.isUnion(definition)) {
481+
if (!this.isInterface(definition)) {
482482
// Reorder properties to put $ first.
483483
let props: any = {
484484
$kind: clone(dialogSchema.definitions.kind),
@@ -516,10 +516,10 @@ export default class DialogMerge extends Command {
516516
}
517517
}
518518

519-
sortUnions(definitions: any): void {
519+
sortImplementations(definitions: any): void {
520520
for (let key in definitions) {
521521
let definition = definitions[key]
522-
if (this.isUnion(definition) && definition.oneOf) {
522+
if (this.isInterface(definition) && definition.oneOf) {
523523
definition.oneOf = definition.oneOf.sort((a: any, b: any) => a.title.localeCompare(b.title))
524524
}
525525
}
@@ -573,8 +573,8 @@ export default class DialogMerge extends Command {
573573
})
574574
}
575575

576-
isUnion(schema: any): boolean {
577-
return schema.$role === 'union'
576+
isInterface(schema: any): boolean {
577+
return schema.$role === 'interface'
578578
}
579579

580580
missing(kind: string): void {

packages/dialog/src/commands/dialog/readme.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Merge
44

5-
Ths will merge together [Microsoft Bot Builder](https://github.com/Microsoft/BotBuilder) .schema JSON schema files into a single JSON schema file. You can point to the files either directly with a glob pattern or indirectly through a glob pattern that matches a package.json, packages.config or \*.csproj file. The .schema files should have a unique filename that is used to refer to that type using `$kind`. The .schema files can optionally include a `$schema: "https://raw.githubusercontent.com/Microsoft/botbuilder-tools/SchemaGen/packages/DialogSchema/src/dialogSchema.schema"` which defines the schema they are validated against. Within a schema definition you can use `$role:"union(<kind>)` to project the type definition into union types defined using `$role:"union"` while merging. To refer to a type in a property, just use `"$kind":"<kind>"`. The merger combines all of the component .schema files into a single .schema file that has resolved all external `$ref`, merged `allOf` and connected together schemas through `$role` and `$kind`.
5+
Ths will merge together [Microsoft Bot Builder](https://github.com/Microsoft/BotBuilder) .schema JSON schema files into a single JSON schema file. You can point to the files either directly with a glob pattern or indirectly through a glob pattern that matches a package.json, packages.config or \*.csproj file. The .schema files should have a unique filename that is used to refer to that type using `$kind`. The .schema files can optionally include a `$schema: "https://raw.githubusercontent.com/Microsoft/botbuilder-tools/SchemaGen/packages/DialogSchema/src/dialogSchema.schema"` which defines the schema they are validated against. Within a schema definition you can use `$role:"implements(<kind>)` to project the type definition into interface types defined using `$role:"interface"` while merging. To refer to a type in a property, just use `"$kind":"<kind>"`. The merger combines all of the component .schema files into a single .schema file that has resolved all external `$ref`, merged `allOf` and connected together schemas through `$role` and `$kind`.
66

77
In addition to types you can also mark properties with a `$role` which will define the underlying type and restrictions. This is also useful information for UI tools to help you construct values. Roles include:
88

@@ -13,7 +13,7 @@ In addition to types you can also mark properties with a `$role` which will defi
1313
For example look at these files:
1414

1515
- [IRecognizer.schema](test/schemas/IRecognizer.schema) defines the place holder for `IRecognizer` including a default option which is a bare string.
16-
- [Recognizer.schema](test/schemas/Recognizer.schema) includes `$role:"union(IRecognizer)"` which extends the `IRecognizer` definition when merged.
16+
- [Recognizer.schema](test/schemas/Recognizer.schema) includes `$role:"implements(IRecognizer)"` which extends the `IRecognizer` definition when merged.
1717
- [root.schema](test/schemas/root.schema) is a schema file that includes `$kind:"IRecognizer"` in order to make use of the `IRecognizer` place holder.
1818
- [app.schema](test/examples/app.schema) was created by this tool shows how all of these definitions are merged together. In particular if you look at `IRecognizer` you will see the definition that includes a string, or the complete definition of `Recognizer`.
1919

packages/dialog/src/library/array.md

Lines changed: 0 additions & 26 deletions
This file was deleted.

packages/dialog/src/library/component.schema

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
"title": "$role",
4848
"description": "Defines the role played in the dialog schema [expression|union|union(Kind)].",
4949
"type": "string",
50-
"pattern": "^((expression)|(union)|(union\\([a-zA-Z][a-zA-Z0-9.]*\\)))$"
50+
"pattern": "^((expression)|(interface)|(implements\\([a-zA-Z][a-zA-Z0-9.]*\\)))$"
5151
},
5252
"id": {
5353
"title": "$id",
@@ -104,6 +104,10 @@
104104
"type": "boolean",
105105
"default": false
106106
},
107+
"writeOnly": {
108+
"type": "boolean",
109+
"default": false
110+
},
107111
"examples": {
108112
"type": "array",
109113
"items": true

packages/dialog/src/library/schemaTracker.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,16 @@ export class SchemaTracker {
3030
added = true
3131
if (schemaObject.oneOf) {
3232
const defRef = '#/definitions/'
33-
const unionRole = 'union('
33+
const implementsRole = 'implements('
3434
let processRole = (role: string, type: Type) => {
35-
if (role.startsWith(unionRole)) {
36-
role = role.substring(unionRole.length, role.length - 1)
37-
let union = this.typeToType.get(role)
38-
if (!union) {
39-
union = new Type(role)
40-
this.typeToType.set(role, union)
35+
if (role.startsWith(implementsRole)) {
36+
role = role.substring(implementsRole.length, role.length - 1)
37+
let interfaceDefinition = this.typeToType.get(role)
38+
if (!interfaceDefinition) {
39+
interfaceDefinition = new Type(role)
40+
this.typeToType.set(role, interfaceDefinition)
4141
}
42-
union.addImplementation(type)
42+
interfaceDefinition.addImplementation(type)
4343
}
4444
}
4545
for (let one of schemaObject.oneOf) {
@@ -134,25 +134,25 @@ export class Type {
134134
// Paths to lg properties for concrete types.
135135
lgProperties: string[]
136136

137-
// Possible types for a union type.
137+
// Possible types for an interface type.
138138
implementations: Type[]
139139

140-
// Union types this type is part of.
141-
unions: Type[]
140+
// Interface types this type implements.
141+
interfaces: Type[]
142142

143143
constructor(name: string, schema?: any) {
144144
this.name = name
145145
this.lgProperties = []
146146
this.implementations = []
147-
this.unions = []
147+
this.interfaces = []
148148
if (schema) {
149149
this.walkProps(schema, name)
150150
}
151151
}
152152

153153
addImplementation(type: Type) {
154154
this.implementations.push(type)
155-
type.unions.push(this)
155+
type.interfaces.push(this)
156156
}
157157

158158
toString(): string {

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@
3030
"INothing": {
3131
"title": "Microsoft Nothing",
3232
"description": "Definition of a union type with no implementations.",
33-
"$role": "union"
33+
"$role": "interface"
3434
},
3535
"IRecognizer": {
36-
"$role": "union",
36+
"$role": "interface",
3737
"oneOf": [
3838
{
3939
"title": "Recognizer",
@@ -48,7 +48,7 @@
4848
]
4949
},
5050
"Recognizer": {
51-
"$role": "union(IRecognizer)",
51+
"$role": "implements(IRecognizer)",
5252
"properties": {
5353
"$kind": {
5454
"title": "$kind",
@@ -116,7 +116,7 @@
116116
]
117117
},
118118
"RecognizerTypeMismatch": {
119-
"$role": "union(IRecognizer)",
119+
"$role": "implements(IRecognizer)",
120120
"type": "object",
121121
"properties": {
122122
"$kind": {

packages/dialog/test/commands/dialog/schemas/INothing.schema

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-dotnet/master/schemas/component.schema",
33
"title": "Microsoft Nothing",
44
"description": "Definition of a union type with no implementations.",
5-
"$role":"union"
5+
"$role":"interface"
66
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-dotnet/master/schemas/component.schema",
3-
"$role": "union"
3+
"$role": "interface"
44
}

packages/dialog/test/commands/dialog/schemas/Recognizer.schema

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-dotnet/master/schemas/component.schema",
3-
"$role": "union(IRecognizer)",
3+
"$role": "implements(IRecognizer)",
44
"properties": {
55
"req": {
66
"$role": "expression"

0 commit comments

Comments
 (0)