fork of hey-api/openapi-ts because I need some additional things
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at feat/use-query-options 119 lines 3.4 kB view raw
1import type { AnalysisContext, NodeName, Ref } from '@hey-api/codegen-core'; 2import { isSymbol, ref } from '@hey-api/codegen-core'; 3 4import { py } from '../../py-compiler'; 5import { type MaybePyDsl, PyDsl } from '../base'; 6import { NewlinePyDsl } from '../layout/newline'; 7import { DecoratorMixin } from '../mixins/decorator'; 8import { DocMixin } from '../mixins/doc'; 9import { LayoutMixin } from '../mixins/layout'; 10import { ExportMixin } from '../mixins/modifiers'; 11import { safeRuntimeName } from '../utils/name'; 12 13type Body = Array<MaybePyDsl<py.Statement>>; 14 15const Mixed = DecoratorMixin(DocMixin(ExportMixin(LayoutMixin(PyDsl<py.ClassDeclaration>)))); 16 17export class ClassPyDsl extends Mixed { 18 readonly '~dsl' = 'ClassPyDsl'; 19 override readonly nameSanitizer = safeRuntimeName; 20 21 protected baseClasses: Array<Ref<NodeName>> = []; 22 protected body: Body = []; 23 24 constructor(name: NodeName) { 25 super(); 26 this.name.set(name); 27 if (isSymbol(name)) { 28 name.setKind('class'); 29 } 30 } 31 32 override analyze(ctx: AnalysisContext): void { 33 super.analyze(ctx); 34 for (const baseClass of this.baseClasses) { 35 ctx.analyze(baseClass); 36 } 37 ctx.analyze(this.name); 38 ctx.pushScope(); 39 try { 40 for (const item of this.body) { 41 ctx.analyze(item); 42 } 43 } finally { 44 ctx.popScope(); 45 } 46 } 47 48 /** Returns true when all required builder calls are present. */ 49 get isValid(): boolean { 50 return !this.missingRequiredCalls().length; 51 } 52 53 /** Returns true if the class has any members. */ 54 get hasBody(): boolean { 55 return Boolean(this.body.length); 56 } 57 58 /** Adds one or more class members (fields, methods, etc.). */ 59 do(...items: Body): this { 60 this.body.push(...items); 61 return this; 62 } 63 64 /** Records base classes to extend from. */ 65 extends(...baseClass: ReadonlyArray<NodeName>): this { 66 this.baseClasses.push(...baseClass.map((item) => ref(item))); 67 return this; 68 } 69 70 /** Inserts an empty line between members for formatting. */ 71 newline(): this { 72 this.body.push(new NewlinePyDsl()); 73 return this; 74 } 75 76 override toAst() { 77 this.$validate(); 78 // const uniqueClasses: Array<py.Expression> = []; 79 80 // for (const base of baseClass) { 81 // let expr: py.Expression; 82 // if (typeof base === 'string' || base instanceof PyDsl) { 83 // expr = this.$node(base) as py.Expression; 84 // } else if (isSymbol(base)) { 85 // expr = py.factory.createIdentifier(base.finalName); 86 // } 87 88 // // Avoid duplicates by checking if already added 89 // const exists = uniqueClasses.some((existing) => { 90 // const existingExpr = this.$node(existing) as py.Expression; 91 // return existingExpr === expr; 92 // }); 93 94 // if (!exists) { 95 // uniqueClasses.push(expr); 96 // } 97 // } 98 99 return py.factory.createClassDeclaration( 100 this.name.toString(), 101 this.$node(this.body), 102 this.$decorators(), 103 this.baseClasses.map((c) => this.$node(c)), 104 this.$docs(), 105 ); 106 } 107 108 $validate(): asserts this { 109 const missing = this.missingRequiredCalls(); 110 if (!missing.length) return; 111 throw new Error(`Class declaration missing ${missing.join(' and ')}`); 112 } 113 114 private missingRequiredCalls(): ReadonlyArray<string> { 115 const missing: Array<string> = []; 116 if (!this.name.toString()) missing.push('name'); 117 return missing; 118 } 119}