@@ -80,16 +80,6 @@ function mergeObjects(obj1: any, obj2: any): any {
8080 return finalTarget
8181}
8282
83- function fileBase ( filename : string ) : string {
84- return filename . substring ( 0 , filename . indexOf ( '.' ) )
85- }
86-
87- function fileLocale ( filename : string ) : string {
88- let extPos = filename . indexOf ( '.' )
89- let localePos = filename . indexOf ( '.' , extPos + 1 )
90- return localePos > 0 ? filename . substring ( extPos + 1 , localePos ) : ''
91- }
92-
9383// Build a tree of component (project or package) references in order to compute a topological sort.
9484class Component {
9585 // Name of component
@@ -216,14 +206,13 @@ export default class SchemaMerger {
216206 private readonly warn : any
217207 private readonly error : any
218208 private readonly extensions : string [ ]
209+ private readonly schemaPath : string | undefined
219210 private readonly debug : boolean | undefined
211+ private nugetRoot = '' // Root where nuget packages are found
220212
221213 // Track packages that have been processed
222214 private readonly packages = new Set ( )
223215
224- // Root where nuget packages are found
225- private nugetRoot = ''
226-
227216 // Component tree
228217 private readonly root = new Component ( )
229218 private readonly parents : Component [ ] = [ ]
@@ -273,17 +262,19 @@ export default class SchemaMerger {
273262 * @param warn Logger for warning messages.
274263 * @param error Logger for error messages.
275264 * @param extensions Extensions to analyze for loader.
265+ * @param schema Path to merged .schema is doin
276266 * @param debug Generate debug output.
277267 * @param nugetRoot Root directory for nuget packages. (Useful for testing.)
278268 */
279- public constructor ( patterns : string [ ] , output : string , verbose : boolean , log : any , warn : any , error : any , extensions ?: string [ ] , debug ?: boolean , nugetRoot ?: string ) {
269+ public constructor ( patterns : string [ ] , output : string , verbose : boolean , log : any , warn : any , error : any , extensions ?: string [ ] , schema ?: string , debug ?: boolean , nugetRoot ?: string ) {
280270 this . patterns = patterns
281- this . output = output ? ppath . join ( ppath . dirname ( output ) , ppath . basename ( output , '.schema' ) ) : ''
271+ this . output = output ? ppath . join ( ppath . dirname ( output ) , ppath . basename ( output , ppath . extname ( output ) ) ) : ''
282272 this . verbose = verbose
283273 this . log = log
284274 this . warn = warn
285275 this . error = error
286276 this . extensions = extensions || [ '.schema' , '.lu' , '.lg' , '.qna' , '.dialog' , '.uischema' ]
277+ this . schemaPath = schema
287278 this . debug = debug
288279 this . nugetRoot = nugetRoot || ''
289280 }
@@ -343,16 +334,33 @@ export default class SchemaMerger {
343334 private async mergeSchemas ( ) : Promise < any > {
344335 let fullSchema : any
345336
337+ if ( this . schemaPath ) {
338+ // Passed in merged schema
339+ this . currentFile = this . schemaPath
340+ let schema = await fs . readJSON ( this . schemaPath )
341+ this . currentFile = schema . $schema
342+ this . metaSchema = await getJSON ( schema . $schema )
343+ this . validator . addSchema ( this . metaSchema , 'componentSchema' )
344+ this . currentFile = this . schemaPath
345+ this . validateSchema ( schema )
346+ return parser . dereference ( schema )
347+ }
348+
346349 // Delete existing output
350+ let outputPath = ppath . resolve ( this . output + '.schema' )
347351 await fs . remove ( this . output + '.schema' )
348352 await fs . remove ( this . output + '.schema.final' )
349353 await fs . remove ( this . output + '.schema.expanded' )
350354
351355 let componentPaths : PathComponent [ ] = [ ]
352356 let schemas = this . files . get ( '.schema' )
353357 if ( schemas ) {
354- for ( let path of schemas . values ( ) ) {
355- componentPaths . push ( path [ 0 ] )
358+ for ( let pathComponents of schemas . values ( ) ) {
359+ // Just take first definition if multiple ones
360+ let pathComponent = pathComponents [ 0 ]
361+ if ( pathComponent . path !== outputPath ) {
362+ componentPaths . push ( pathComponent )
363+ }
356364 }
357365 }
358366
@@ -377,8 +385,10 @@ export default class SchemaMerger {
377385 delete component . $ref
378386 }
379387
380- // Pick up meta-schema from first .dialog file
381- if ( ! this . metaSchema ) {
388+ if ( ! component . $schema ) {
389+ this . missingSchemaError ( )
390+ } else if ( ! this . metaSchema ) {
391+ // Pick up meta-schema from first .dialog file
382392 this . metaSchemaId = component . $schema
383393 this . currentFile = this . metaSchemaId
384394 this . metaSchema = await getJSON ( component . $schema )
@@ -485,13 +495,20 @@ export default class SchemaMerger {
485495 let uiSchemas = this . files . get ( '.uischema' )
486496 let result = { }
487497 if ( uiSchemas ) {
498+ if ( ! schema || this . failed ) {
499+ this . error ( 'Error must have a merged .schema to merge .uischema files' )
500+ return
501+ }
502+
488503 this . log ( 'Merging component .uischema files' )
504+ if ( this . schemaPath ) {
505+ this . log ( `Using merged schema ${ this . schemaPath } ` )
506+ }
489507 let outputName = ppath . basename ( this . output )
490508 for ( let [ fileName , componentPaths ] of uiSchemas . entries ( ) ) {
491509 // Skip files that match output .uischema
492510 if ( ! fileName . startsWith ( outputName + '.' ) ) {
493- let kindName = fileBase ( fileName )
494- let localeName = fileLocale ( fileName )
511+ let [ kindName , localeName ] = this . kindAndLocale ( fileName , schema )
495512 let locale = result [ localeName ]
496513 if ( ! locale ) {
497514 locale = result [ localeName ] = { }
@@ -511,9 +528,10 @@ export default class SchemaMerger {
511528 this . vlog ( `Parsing ${ this . currentFile } ` )
512529 }
513530 let component = await fs . readJSON ( path )
514-
515- // Pick up meta-schema from first .uischema file
516- if ( ! this . metaUISchema ) {
531+ if ( ! component . $schema ) {
532+ this . missingSchemaError ( )
533+ } else if ( ! this . metaUISchema ) {
534+ // Pick up meta-schema from first .uischema file
517535 this . metaUISchemaId = component . $schema
518536 this . currentFile = this . metaUISchemaId
519537 this . metaUISchema = await getJSON ( component . $schema )
@@ -526,6 +544,7 @@ export default class SchemaMerger {
526544 } else {
527545 this . validateUISchema ( component )
528546 }
547+ delete component . $schema
529548 locale [ kindName ] = mergeObjects ( locale [ kindName ] , component )
530549 } catch ( e ) {
531550 this . parsingError ( e )
@@ -542,18 +561,32 @@ export default class SchemaMerger {
542561 }
543562 }
544563 if ( ! this . failed ) {
545- for ( let locale in result ) {
564+ for ( let locale of Object . keys ( result ) ) {
565+ let uischema = { $schema : this . metaUISchemaId , ...result [ locale ] }
546566 this . currentFile = ppath . join ( ppath . dirname ( this . output ) , outputName + ( locale ? '.' + locale : '' ) + '.uischema' )
547567 this . log ( `Writing ${ this . currentFile } ` )
548- await fs . writeJSON ( this . currentFile , result [ locale ] , this . jsonOptions )
568+ await fs . writeJSON ( this . currentFile , uischema , this . jsonOptions )
549569 }
550570 }
551571 }
552572 }
553573
574+ private kindAndLocale ( filename : string , schema : any ) : [ string , string ] {
575+ let kindName = ppath . basename ( filename , '.uischema' )
576+ let locale = ''
577+ if ( ! schema . definitions [ kindName ] ) {
578+ let split = kindName . lastIndexOf ( '.' )
579+ if ( split >= 0 ) {
580+ locale = kindName . substring ( split + 1 )
581+ kindName = kindName . substring ( 0 , split )
582+ }
583+ }
584+ return [ kindName , locale ]
585+ }
586+
554587 // For C# copy all assets into generated/<package>/
555588 private async copyAssets ( ) : Promise < void > {
556- if ( ! this . failed ) {
589+ if ( ! this . failed && ! this . schemaPath ) {
557590 let isCS = false
558591 for ( let component of this . components ) {
559592 if ( component . path . endsWith ( '.csproj' ) || component . path . endsWith ( '.nuspec' ) ) {
@@ -569,7 +602,8 @@ export default class SchemaMerger {
569602 for ( let componentPath of componentPaths ) {
570603 let component = componentPath . component
571604 let path = componentPath . path
572- if ( ! component . isCSProject ( ) ) {
605+ // Don't copy .schema/.uischema so that we don't pick-up in project
606+ if ( ! component . isCSProject ( ) && ! path . endsWith ( '.schema' ) && ! path . endsWith ( '.uischema' ) ) {
573607 // Copy package files to output
574608 let relativePath = ppath . relative ( ppath . dirname ( component . path ) , path )
575609 let outputPath = ppath . join ( generatedPath , componentPath . component . name , relativePath )
@@ -728,7 +762,6 @@ export default class SchemaMerger {
728762 for ( let dependency of group . dependency ) {
729763 dependencies . push ( dependency . $ )
730764 }
731- break
732765 }
733766 }
734767 }
@@ -743,8 +776,8 @@ export default class SchemaMerger {
743776 } finally {
744777 this . popParent ( )
745778 }
746- } else {
747- this . parsingError ( ' Could not find nuspec' )
779+ } else if ( this . debug ) {
780+ this . parsingWarning ( ' Could not find nuspec' )
748781 }
749782 }
750783 }
@@ -768,8 +801,12 @@ export default class SchemaMerger {
768801 pkgPath = ppath . join ( pkgPath , version || '' )
769802 let nuspecPath = ppath . join ( pkgPath , `${ packageName } .nuspec` )
770803 await this . expandNuspec ( nuspecPath )
771- } else {
772- this . parsingError ( ' Nuget package does not exist' )
804+ } else if ( this . debug ) {
805+ // Ignore any missing dependencies assuming they are from a target framework like this:
806+ // <group targetFramework=".NETFramework4.0">
807+ // <dependency id="Microsoft.Diagnostics.Tracing.EventSource.Redist" version = "1.1.28" />
808+ // </group>
809+ this . parsingWarning ( 'Missing package' )
773810 }
774811 } catch ( e ) {
775812 this . parsingWarning ( e . message )
@@ -1449,6 +1486,12 @@ export default class SchemaMerger {
14491486 }
14501487 }
14511488
1489+ // Missing $schema
1490+ private missingSchemaError ( ) {
1491+ this . error ( `${ this . currentFile } : Error missing $schema` )
1492+ this . failed = true
1493+ }
1494+
14521495 // Error in schema validity
14531496 private schemaError ( err : Validator . ErrorObject ) : void {
14541497 this . error ( `${ this . currentFile } : ${ err . dataPath } error: ${ err . message } ` )
0 commit comments