From e81d9b0221d163acec4ce0b183a40368a5ee4ac2 Mon Sep 17 00:00:00 2001 From: Steve Konves Date: Tue, 12 Aug 2025 20:41:49 -0700 Subject: [PATCH] Parse interface descriptions --- src/parser.ts | 59 +++++++++++++++++++++++++++++--------- src/snapshot/petstore.json | 9 ++++++ 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/src/parser.ts b/src/parser.ts index a1ee849..24aa204 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1,6 +1,6 @@ import { major } from 'semver'; import { singular } from 'pluralize'; -import { camel, kebab, pascal } from 'case'; +import { camel, kebab, pascal, snake } from 'case'; import { AST, DocumentNode, NodeConstructor, parse } from '@basketry/ast'; import * as OAS3 from './types'; @@ -199,13 +199,18 @@ export class OAS3Parser { } private parseInterfaces(): Interface[] { - return this.parserInterfaceNames().map((name) => ({ + return this.parserInterfaceNames().map(({ name, description }) => ({ kind: 'Interface', - name: { kind: 'StringLiteral', value: singular(name) }, - methods: this.parseMethods(name), + name: { + kind: 'StringLiteral', + value: singular(name.value), + loc: name.loc, + }, + description, + methods: this.parseMethods(name.value), protocols: { kind: 'InterfaceProtocols', - http: this.parseHttpProtocol(name), + http: this.parseHttpProtocol(name.value), }, })); } @@ -285,7 +290,9 @@ export class OAS3Parser { const operation = pathItem[verb] as OAS3.OperationNode | undefined; if (!operation) continue; - if (this.parseInterfaceName(path, operation) !== interfaceName) { + if ( + this.parseInterfaceName(path, operation).name.value !== interfaceName + ) { continue; } @@ -489,20 +496,44 @@ export class OAS3Parser { } } - private parserInterfaceNames(): string[] { - const interfaceNames = new Set(); + private parserInterfaceNames(): { + name: StringLiteral; + description: StringLiteral[] | undefined; + }[] { + const interfaceNames = new Map< + string, + { name: StringLiteral; description: StringLiteral[] | undefined } + >(); for (const { path, operation } of this.allOperations()) { - interfaceNames.add(this.parseInterfaceName(path, operation)); + const { name, description } = this.parseInterfaceName(path, operation); + interfaceNames.set(name.value, { name, description }); } - return Array.from(interfaceNames); + return Array.from(interfaceNames.values()); } private parseInterfaceName( path: string, operation: OAS3.OperationNode, - ): string { + ): { name: StringLiteral; description: StringLiteral[] | undefined } { const segments = path.split('/'); - return operation.tags?.[0].value || segments[1] || segments[0] || 'default'; + + const tag = operation.tags?.[0]; + + const name: StringLiteral = tag + ? { kind: 'StringLiteral', value: tag.value, loc: range(tag) } + : { + kind: 'StringLiteral', + value: segments[1] || segments[0] || 'default', + }; + + const description = this.schema.tags?.find( + (t) => snake(t.name?.value ?? '') === snake(name.value), + )?.description; + + return { + name, + description: this.parseDescription(description, undefined), + }; } private parseDeprecated(node: { @@ -524,7 +555,9 @@ export class OAS3Parser { const pathNode = this.resolve(pathsNode.read(path)!, OAS3.PathItemNode); const commonParameters = pathNode?.parameters ?? []; - if (this.parseInterfaceName(path, operation) !== interfaceName) { + if ( + this.parseInterfaceName(path, operation).name.value !== interfaceName + ) { continue; } diff --git a/src/snapshot/petstore.json b/src/snapshot/petstore.json index 8089341..58e66fb 100644 --- a/src/snapshot/petstore.json +++ b/src/snapshot/petstore.json @@ -8,6 +8,9 @@ { "kind": "Interface", "name": { "kind": "StringLiteral", "value": "pet" }, + "description": [ + { "kind": "StringLiteral", "value": "Everything about your Pets" } + ], "methods": [ { "kind": "Method", @@ -1055,6 +1058,9 @@ { "kind": "Interface", "name": { "kind": "StringLiteral", "value": "store" }, + "description": [ + { "kind": "StringLiteral", "value": "Access to Petstore orders" } + ], "methods": [ { "kind": "Method", @@ -1314,6 +1320,9 @@ { "kind": "Interface", "name": { "kind": "StringLiteral", "value": "user" }, + "description": [ + { "kind": "StringLiteral", "value": "Operations about user" } + ], "methods": [ { "kind": "Method",