Skip to content

Commit 59eaa8d

Browse files
committed
fix: false-positive recursive detection with oneOf
fixes #723, fixes #585
1 parent e2d0cd5 commit 59eaa8d

File tree

2 files changed

+35
-20
lines changed

2 files changed

+35
-20
lines changed

src/services/OpenAPIParser.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,12 @@ export class OpenAPIParser {
291291
return res;
292292
}
293293

294+
exitParents(shema: MergedOpenAPISchema) {
295+
for (const parent$ref of shema.parentRefs || []) {
296+
this.exitRef({ $ref: parent$ref });
297+
}
298+
}
299+
294300
private hoistOneOfs(schema: OpenAPISchema) {
295301
if (schema.allOf === undefined) {
296302
return schema;
@@ -304,9 +310,14 @@ export class OpenAPIParser {
304310
const afterAllOf = allOf.slice(i + 1);
305311
return {
306312
oneOf: sub.oneOf.map(part => {
307-
return this.mergeAllOf({
313+
const merged = this.mergeAllOf({
308314
allOf: [...beforeAllOf, part, ...afterAllOf],
309315
});
316+
317+
// each oneOf should be independent so exiting all the parent refs
318+
// otherwise it will cause false-positive recursive detection
319+
this.exitParents(merged);
320+
return merged;
310321
}),
311322
};
312323
}

src/services/models/Schema.ts

+23-19
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,7 @@ export class SchemaModel {
7575
this.init(parser, isChild);
7676

7777
parser.exitRef(schemaOrRef);
78-
79-
for (const parent$ref of this.schema.parentRefs || []) {
80-
// exit all the refs visited during allOf traverse
81-
parser.exitRef({ $ref: parent$ref });
82-
}
78+
parser.exitParents(this.schema);
8379

8480
if (options.showExtensions) {
8581
this.extensions = extractExtensions(this.schema, options.showExtensions);
@@ -164,20 +160,28 @@ export class SchemaModel {
164160
}
165161

166162
private initOneOf(oneOf: OpenAPISchema[], parser: OpenAPIParser) {
167-
this.oneOf = oneOf!.map(
168-
(variant, idx) =>
169-
new SchemaModel(
170-
parser,
171-
// merge base schema into each of oneOf's subschemas
172-
{
173-
// variant may already have allOf so merge it to not get overwritten
174-
...parser.mergeAllOf(variant, this.pointer + '/oneOf/' + idx),
175-
allOf: [{ ...this.schema, oneOf: undefined, anyOf: undefined }],
176-
} as OpenAPISchema,
177-
this.pointer + '/oneOf/' + idx,
178-
this.options,
179-
),
180-
);
163+
this.oneOf = oneOf!.map((variant, idx) => {
164+
const merged = parser.mergeAllOf(variant, this.pointer + '/oneOf/' + idx);
165+
166+
const schema = new SchemaModel(
167+
parser,
168+
// merge base schema into each of oneOf's subschemas
169+
{
170+
// variant may already have allOf so merge it to not get overwritten
171+
...merged,
172+
allOf: [{ ...this.schema, oneOf: undefined, anyOf: undefined }],
173+
} as OpenAPISchema,
174+
this.pointer + '/oneOf/' + idx,
175+
this.options,
176+
);
177+
178+
// each oneOf should be independent so exiting all the parent refs
179+
// otherwise it will cause false-positive recursive detection
180+
parser.exitParents(merged);
181+
182+
return schema;
183+
});
184+
181185
this.displayType = this.oneOf
182186
.map(schema => {
183187
let name =

0 commit comments

Comments
 (0)