mirror of
https://github.com/Redocly/redoc.git
synced 2025-08-08 22:24:54 +03:00
Fix #1154
Immediately exit from allOf's children, but use separate refCounter to do not enter into same scheme recursively Also add pseudo-recursive example
This commit is contained in:
parent
c05db38576
commit
d5890fc26b
58
demo/pseudo-recursive.yaml
Normal file
58
demo/pseudo-recursive.yaml
Normal file
|
@ -0,0 +1,58 @@
|
|||
openapi: 3.0.0
|
||||
info:
|
||||
title: False positive recursion
|
||||
version: '3.0'
|
||||
tags:
|
||||
- name: a
|
||||
|
||||
components:
|
||||
schemas:
|
||||
id:
|
||||
tags:
|
||||
- a
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: number
|
||||
description: id
|
||||
pet:
|
||||
tags:
|
||||
- a
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
friends:
|
||||
type: array
|
||||
items:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/pet'
|
||||
paths:
|
||||
/documents:
|
||||
get:
|
||||
summary: Example
|
||||
responses:
|
||||
'200':
|
||||
description: Pseudo-recursvie
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/id'
|
||||
- properties:
|
||||
second:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/id'
|
||||
- properties:
|
||||
third:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/id'
|
||||
- properties:
|
||||
something:
|
||||
type: string
|
||||
'204':
|
||||
description: Recursvie
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/pet'
|
|
@ -18,7 +18,7 @@ export type MergedOpenAPISchema = OpenAPISchema & { parentRefs?: string[] };
|
|||
* Helper class to keep track of visited references to avoid
|
||||
* endless recursion because of circular refs
|
||||
*/
|
||||
class RefCounter {
|
||||
export class RefCounter {
|
||||
_counter = {};
|
||||
|
||||
reset(): void {
|
||||
|
@ -46,6 +46,8 @@ export class OpenAPIParser {
|
|||
spec: OpenAPISpec;
|
||||
mergeRefs: Set<string>;
|
||||
|
||||
schemaCounter: RefCounter = new RefCounter();
|
||||
|
||||
private _refCounter: RefCounter = new RefCounter();
|
||||
|
||||
constructor(
|
||||
|
@ -221,6 +223,7 @@ export class OpenAPIParser {
|
|||
|
||||
const resolved = this.deref(subSchema, forceCircular);
|
||||
const subRef = subSchema.$ref || undefined;
|
||||
this.exitRef(subSchema);
|
||||
const subMerged = this.mergeAllOf(resolved, subRef, forceCircular, used$Refs);
|
||||
receiver.parentRefs!.push(...(subMerged.parentRefs || []));
|
||||
return {
|
||||
|
@ -311,8 +314,8 @@ export class OpenAPIParser {
|
|||
return res;
|
||||
}
|
||||
|
||||
exitParents(shema: MergedOpenAPISchema) {
|
||||
for (const parent$ref of shema.parentRefs || []) {
|
||||
exitParents(schema: MergedOpenAPISchema) {
|
||||
for (const parent$ref of schema.parentRefs || []) {
|
||||
this.exitRef({ $ref: parent$ref });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { action, observable } from 'mobx';
|
|||
|
||||
import { OpenAPIExternalDocumentation, OpenAPISchema, Referenced } from '../../types';
|
||||
|
||||
import { OpenAPIParser } from '../OpenAPIParser';
|
||||
import {OpenAPIParser, RefCounter} from '../OpenAPIParser';
|
||||
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
||||
import { FieldModel } from './Field';
|
||||
|
||||
|
@ -21,6 +21,8 @@ import {
|
|||
|
||||
import { l } from '../Labels';
|
||||
|
||||
const schemaCounter = new RefCounter();
|
||||
|
||||
// TODO: refactor this model, maybe use getters instead of copying all the values
|
||||
export class SchemaModel {
|
||||
pointer: string;
|
||||
|
@ -73,16 +75,26 @@ export class SchemaModel {
|
|||
isChild: boolean = false,
|
||||
) {
|
||||
this.pointer = schemaOrRef.$ref || pointer || '';
|
||||
this.rawSchema = parser.deref(schemaOrRef);
|
||||
this.schema = parser.mergeAllOf(this.rawSchema, this.pointer, isChild);
|
||||
let visited = false;
|
||||
if (this.pointer) {
|
||||
visited = schemaCounter.visited(this.pointer);
|
||||
schemaCounter.visit(this.pointer);
|
||||
}
|
||||
if (!visited) {
|
||||
this.rawSchema = parser.deref(schemaOrRef);
|
||||
this.schema = parser.mergeAllOf(this.rawSchema, this.pointer, isChild);
|
||||
|
||||
this.init(parser, isChild);
|
||||
this.init(parser, isChild);
|
||||
|
||||
parser.exitRef(schemaOrRef);
|
||||
parser.exitParents(this.schema);
|
||||
parser.exitRef(schemaOrRef);
|
||||
parser.exitParents(this.schema);
|
||||
|
||||
if (options.showExtensions) {
|
||||
this.extensions = extractExtensions(this.schema, options.showExtensions);
|
||||
if (options.showExtensions) {
|
||||
this.extensions = extractExtensions(this.schema, options.showExtensions);
|
||||
}
|
||||
}
|
||||
if (this.pointer) {
|
||||
schemaCounter.exit(this.pointer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user