diff --git a/src/services/OpenAPIParser.ts b/src/services/OpenAPIParser.ts index f841dd2451..37a6e13887 100644 --- a/src/services/OpenAPIParser.ts +++ b/src/services/OpenAPIParser.ts @@ -291,6 +291,12 @@ export class OpenAPIParser { return res; } + exitParents(shema: MergedOpenAPISchema) { + for (const parent$ref of shema.parentRefs || []) { + this.exitRef({ $ref: parent$ref }); + } + } + private hoistOneOfs(schema: OpenAPISchema) { if (schema.allOf === undefined) { return schema; @@ -304,9 +310,14 @@ export class OpenAPIParser { const afterAllOf = allOf.slice(i + 1); return { oneOf: sub.oneOf.map(part => { - return this.mergeAllOf({ + const merged = this.mergeAllOf({ allOf: [...beforeAllOf, part, ...afterAllOf], }); + + // each oneOf should be independent so exiting all the parent refs + // otherwise it will cause false-positive recursive detection + this.exitParents(merged); + return merged; }), }; } diff --git a/src/services/models/Schema.ts b/src/services/models/Schema.ts index e5b69fcb85..b2984c82b1 100644 --- a/src/services/models/Schema.ts +++ b/src/services/models/Schema.ts @@ -75,11 +75,7 @@ export class SchemaModel { this.init(parser, isChild); parser.exitRef(schemaOrRef); - - for (const parent$ref of this.schema.parentRefs || []) { - // exit all the refs visited during allOf traverse - parser.exitRef({ $ref: parent$ref }); - } + parser.exitParents(this.schema); if (options.showExtensions) { this.extensions = extractExtensions(this.schema, options.showExtensions); @@ -164,20 +160,28 @@ export class SchemaModel { } private initOneOf(oneOf: OpenAPISchema[], parser: OpenAPIParser) { - this.oneOf = oneOf!.map( - (variant, idx) => - new SchemaModel( - parser, - // merge base schema into each of oneOf's subschemas - { - // variant may already have allOf so merge it to not get overwritten - ...parser.mergeAllOf(variant, this.pointer + '/oneOf/' + idx), - allOf: [{ ...this.schema, oneOf: undefined, anyOf: undefined }], - } as OpenAPISchema, - this.pointer + '/oneOf/' + idx, - this.options, - ), - ); + this.oneOf = oneOf!.map((variant, idx) => { + const merged = parser.mergeAllOf(variant, this.pointer + '/oneOf/' + idx); + + const schema = new SchemaModel( + parser, + // merge base schema into each of oneOf's subschemas + { + // variant may already have allOf so merge it to not get overwritten + ...merged, + allOf: [{ ...this.schema, oneOf: undefined, anyOf: undefined }], + } as OpenAPISchema, + this.pointer + '/oneOf/' + idx, + this.options, + ); + + // each oneOf should be independent so exiting all the parent refs + // otherwise it will cause false-positive recursive detection + parser.exitParents(merged); + + return schema; + }); + this.displayType = this.oneOf .map(schema => { let name =