Skip to content

Commit

Permalink
feat: consolidate comments from nested levels of schemas
Browse files Browse the repository at this point in the history
  • Loading branch information
ad-world committed Jul 30, 2024
1 parent 77ad820 commit 91a5de1
Show file tree
Hide file tree
Showing 3 changed files with 468 additions and 34 deletions.
67 changes: 67 additions & 0 deletions packages/openapi-generator/src/comments.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { parse as parseComment, Block } from 'comment-parser';
import { Schema } from './ir';

export function leadingComment(
src: string,
Expand Down Expand Up @@ -42,3 +43,69 @@ export function leadingComment(
const parsedComment = parseComment(commentString);
return parsedComment;
}

/**
*
* @param schema the schema to get all comments from
* @returns an array of all comments in the schema
*/
export function getAllSchemaComments(schema: Schema): Block[] {
const result = [];

/** Push the first comment */
if (schema.comment) {
result.push(schema.comment);
}

/** Push the comments of the subschemas in CombinedTypes (union, intersection, etc) */
if ('schemas' in schema) {
// combined type
for (const s of schema.schemas) {
result.push(...getAllSchemaComments(s));
}
}

return result;
}

/**
*
* @param schema the schema to combine comments from
* @returns a combined comment from all comments in the schema
*/
export function combineComments(schema: Schema): Block | undefined {
const comments = getAllSchemaComments(schema);

const tagSet = new Set<string>();

// Empty comment block where we will build the result
const result: Block = {
tags: [],
description: '',
problems: [],
source: [],
};

if (comments.length === 0) return undefined;

// Only use the first description if it exists, we don't wanna accidentally pull a description from a lower level schema
if (comments[0]?.description && comments[0].description !== '') {
result.description = comments[0].description;
}

// Add all seen tags, problems, and source comments to the result
for (const comment of comments) {
for (const tag of comment.tags) {
// Only add the tag if we haven't seen it before. Otherwise, the higher level tag is 'probably' the more relevant tag.
if (!tagSet.has(tag.tag)) {
result.tags.push(tag);
tagSet.add(tag.tag);
}
}

result.problems.push(...comment.problems);
result.source.push(...comment.source);
}

return result;
}
53 changes: 20 additions & 33 deletions packages/openapi-generator/src/optimize.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { combineComments } from './comments';
import { isPrimitive, type Primitive, type Schema } from './ir';

export type OptimizeFn = (schema: Schema) => Schema;
Expand Down Expand Up @@ -173,6 +174,15 @@ export function filterUndefinedUnion(schema: Schema): [boolean, Schema] {
}
}

// This function is a helper that adds back any comments that were removed during optimization
function withComment(newSchema: Schema, oldSchema: Schema): Schema {
if (oldSchema.comment) {
newSchema.comment = combineComments(oldSchema);
}

return newSchema;
}

export function optimize(schema: Schema): Schema {
if (schema.type === 'object') {
const properties: Record<string, Schema> = {};
Expand All @@ -184,8 +194,8 @@ export function optimize(schema: Schema): Schema {
}
const [isOptional, filteredSchema] = filterUndefinedUnion(optimized);

if (prop.comment) {
filteredSchema.comment = prop.comment;
if (optimized.comment) {
filteredSchema.comment = optimized.comment;
}

properties[key] = filteredSchema;
Expand All @@ -197,50 +207,27 @@ export function optimize(schema: Schema): Schema {

const schemaObject: Schema = { type: 'object', properties, required };

// only add comment field if there is a comment
if (schema.comment) {
return { ...schemaObject, comment: schema.comment };
}

return schemaObject;
return withComment(schemaObject, schema);
} else if (schema.type === 'intersection') {
const newSchema = foldIntersection(schema, optimize);
if (schema.comment) {
return { ...newSchema, comment: schema.comment };
}
return newSchema;

return withComment(newSchema, schema);
} else if (schema.type === 'union') {
const consolidated = consolidateUnion(schema);
const simplified = simplifyUnion(consolidated, optimize);
const merged = mergeUnions(simplified);

if (schema.comment) {
return { ...merged, comment: schema.comment };
}

return merged;
return withComment(merged, schema);
} else if (schema.type === 'array') {
const optimized = optimize(schema.items);
if (schema.comment) {
return { type: 'array', items: optimized, comment: schema.comment };
}
return { type: 'array', items: optimized };

return withComment({ type: 'array', items: optimized }, schema);
} else if (schema.type === 'record') {
if (schema.comment) {
return {
type: 'record',
codomain: optimize(schema.codomain),
comment: schema.comment,
};
}
return { type: 'record', codomain: optimize(schema.codomain) };
return withComment({ type: 'record', codomain: optimize(schema.codomain) }, schema);
} else if (schema.type === 'tuple') {
const schemas = schema.schemas.map(optimize);
return { type: 'tuple', schemas };
return withComment({ type: 'tuple', schemas }, schema);
} else if (schema.type === 'ref') {
if (schema.comment) {
return { ...schema, comment: schema.comment };
}
return schema;
} else {
return schema;
Expand Down
Loading

0 comments on commit 91a5de1

Please sign in to comment.