fix: false-positive recursive detection with oneOf

fixes #723, fixes #585
This commit is contained in:
Roman Hotsiy 2018-11-27 12:21:28 +02:00
parent e2d0cd5b18
commit 59eaa8d633
No known key found for this signature in database
GPG Key ID: 5CB7B3ACABA57CB0
2 changed files with 35 additions and 20 deletions

View File

@ -291,6 +291,12 @@ export class OpenAPIParser {
return res; return res;
} }
exitParents(shema: MergedOpenAPISchema) {
for (const parent$ref of shema.parentRefs || []) {
this.exitRef({ $ref: parent$ref });
}
}
private hoistOneOfs(schema: OpenAPISchema) { private hoistOneOfs(schema: OpenAPISchema) {
if (schema.allOf === undefined) { if (schema.allOf === undefined) {
return schema; return schema;
@ -304,9 +310,14 @@ export class OpenAPIParser {
const afterAllOf = allOf.slice(i + 1); const afterAllOf = allOf.slice(i + 1);
return { return {
oneOf: sub.oneOf.map(part => { oneOf: sub.oneOf.map(part => {
return this.mergeAllOf({ const merged = this.mergeAllOf({
allOf: [...beforeAllOf, part, ...afterAllOf], 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;
}), }),
}; };
} }

View File

@ -75,11 +75,7 @@ export class SchemaModel {
this.init(parser, isChild); this.init(parser, isChild);
parser.exitRef(schemaOrRef); parser.exitRef(schemaOrRef);
parser.exitParents(this.schema);
for (const parent$ref of this.schema.parentRefs || []) {
// exit all the refs visited during allOf traverse
parser.exitRef({ $ref: parent$ref });
}
if (options.showExtensions) { if (options.showExtensions) {
this.extensions = extractExtensions(this.schema, options.showExtensions); this.extensions = extractExtensions(this.schema, options.showExtensions);
@ -164,20 +160,28 @@ export class SchemaModel {
} }
private initOneOf(oneOf: OpenAPISchema[], parser: OpenAPIParser) { private initOneOf(oneOf: OpenAPISchema[], parser: OpenAPIParser) {
this.oneOf = oneOf!.map( this.oneOf = oneOf!.map((variant, idx) => {
(variant, idx) => const merged = parser.mergeAllOf(variant, this.pointer + '/oneOf/' + idx);
new SchemaModel(
parser, const schema = new SchemaModel(
// merge base schema into each of oneOf's subschemas 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), // variant may already have allOf so merge it to not get overwritten
allOf: [{ ...this.schema, oneOf: undefined, anyOf: undefined }], ...merged,
} as OpenAPISchema, allOf: [{ ...this.schema, oneOf: undefined, anyOf: undefined }],
this.pointer + '/oneOf/' + idx, } as OpenAPISchema,
this.options, 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 this.displayType = this.oneOf
.map(schema => { .map(schema => {
let name = let name =