@@ -6,18 +6,6 @@ function cppIdentifer(s: string) {
66 return helpers . snakeToPascalCase ( s ) ;
77}
88
9- function objectReferencesObject ( existing : ObjectType , name : string ) {
10- for ( const prop of existing . properties ) {
11- if ( prop . kind === 'object' ) {
12- const object = prop as ObjectType
13- if ( object . name === name ) {
14- return true
15- }
16- }
17- }
18- return false
19- }
20-
219function v2ToCppTypeXInner ( type : XtpNormalizedType , refnamespace : string ) : string {
2210 switch ( type . kind ) {
2311 case 'string' :
@@ -328,29 +316,89 @@ function isTypeUntypedObject(type: XtpNormalizedType) {
328316 return false
329317}
330318
319+ function addObject ( objects : Schema [ ] , schema : Schema ) {
320+ // find the object's direct dependencies
321+ const names = new Set ( ) ;
322+ const object = schema . xtpType as ObjectType
323+ for ( const prop of object . properties ) {
324+ if ( prop . kind === 'object' ) {
325+ const object = prop as ObjectType
326+ if ( object . name ) {
327+ names . add ( object . name )
328+ }
329+ } else if ( prop . kind === 'array' ) {
330+ const arrayType = prop as ArrayType
331+ if ( arrayType . elementType . kind === 'object' ) {
332+ const object = arrayType . elementType as ObjectType
333+ if ( object . name ) {
334+ names . add ( object . name )
335+ }
336+ }
337+ } else if ( prop . kind === 'map' ) {
338+ const { keyType, valueType } = prop as MapType
339+ if ( valueType . kind === 'object' ) {
340+ const object = valueType as ObjectType
341+ if ( object . name ) {
342+ names . add ( object . name )
343+ }
344+ }
345+ }
346+ }
347+ // loop until after the dependencies or end of objects
348+ let i = 0 ;
349+ for ( ; i < objects . length ; i ++ ) {
350+ if ( names . size === 0 ) {
351+ break
352+ }
353+ const existing = objects [ i ]
354+ const existingObject = existing . xtpType as ObjectType ;
355+ names . delete ( existingObject . name )
356+ }
357+ // not all deps found, can't add yet
358+ if ( names . size ) {
359+ return false
360+ }
361+ // add
362+ objects . splice ( i , 0 , schema ) ;
363+ return true
364+ }
365+
331366export function render ( ) {
332367 const tmpl = Host . inputString ( ) ;
333368 const prevctx = getContext ( ) ;
334369
335370 const enums : Schema [ ] = [ ] ;
371+ const todoObjects : Schema [ ] = [ ] ;
336372 const objects : Schema [ ] = [ ] ;
337- Object . values ( prevctx . schema . schemas ) . forEach ( schema => {
373+ for ( const schema of Object . values ( prevctx . schema . schemas ) ) {
338374 if ( helpers . isEnum ( schema ) ) {
339375 enums . push ( schema ) ;
340376 } else if ( helpers . isObject ( schema ) ) {
341- const object = schema . xtpType as ObjectType ;
342- // insertion sort objects ahead of objects that use them
343- let i = 0 ;
344- for ( ; i < objects . length ; i ++ ) {
345- if ( objectReferencesObject ( objects [ i ] . xtpType as ObjectType , object . name ) ) {
346- break ;
347- }
377+ // insertion sort add object after its dependencies
378+ // if it's dependencies aren't in objects, defer
379+ if ( ! addObject ( objects , schema ) ) {
380+ todoObjects . push ( schema )
348381 }
349- objects . splice ( i , 0 , schema ) ; // we need Schema as it has the required attribute
350382 } else {
351383 throw new Error ( "unhandled schema type " + schema . xtpType . kind )
352384 }
353- } ) ;
385+ }
386+ // add the remaining objects
387+ // rather than doing dependency analysis
388+ // each iteration loop through all the objects until we add an object
389+ const maxIterations = todoObjects . length
390+ for ( let iter = 0 ; iter < maxIterations ; iter ++ ) {
391+ for ( let i = 0 ; i < todoObjects . length ; i ++ ) {
392+ if ( addObject ( objects , todoObjects [ i ] ) ) {
393+ todoObjects . splice ( i , 1 )
394+ break
395+ }
396+ }
397+ }
398+ if ( todoObjects . length ) {
399+ throw new Error ( "Failed to add remaning objects" )
400+ }
401+
354402 // sort the properties for efficient struct layout
355403 for ( const object of objects ) {
356404 object . properties . sort ( ( a : Property , b : Property ) => {
0 commit comments