fork of hey-api/openapi-ts because I need some additional things
at feat/skip-token 89 lines 2.7 kB view raw
1import type { AnalysisContext, NodeName } from '@hey-api/codegen-core'; 2import { isSymbol } from '@hey-api/codegen-core'; 3 4import { py } from '../../ts-python'; 5import { PyDsl } from '../base'; 6import { DecoratorMixin } from '../mixins/decorator'; 7import { DoMixin } from '../mixins/do'; 8import { DocMixin } from '../mixins/doc'; 9import { LayoutMixin } from '../mixins/layout'; 10import { AsyncMixin, ModifiersMixin } from '../mixins/modifiers'; 11import { safeRuntimeName } from '../utils/name'; 12 13const Mixed = DecoratorMixin( 14 DocMixin(DoMixin(LayoutMixin(AsyncMixin(ModifiersMixin(PyDsl<py.FunctionDeclaration>))))), 15); 16 17export class FuncPyDsl extends Mixed { 18 readonly '~dsl' = 'FuncPyDsl'; 19 override readonly nameSanitizer = safeRuntimeName; 20 21 protected _parameters: Array<py.FunctionParameter> = []; 22 protected _returnType?: py.Expression; 23 24 constructor(name: NodeName, fn?: (f: FuncPyDsl) => void) { 25 super(); 26 this.name.set(name); 27 if (isSymbol(name)) { 28 name.setKind('function'); 29 } 30 fn?.(this); 31 } 32 33 override analyze(ctx: AnalysisContext): void { 34 ctx.pushScope(); 35 try { 36 super.analyze(ctx); 37 ctx.analyze(this.name); 38 } finally { 39 ctx.popScope(); 40 } 41 for (const param of this._parameters) { 42 ctx.analyze(param); 43 } 44 ctx.analyze(this._returnType); 45 } 46 47 /** Returns true when all required builder calls are present. */ 48 get isValid(): boolean { 49 return this.missingRequiredCalls().length === 0; 50 } 51 52 param(name: string, configure?: (p: py.FunctionParameter) => void): this { 53 const param = py.factory.createFunctionParameter(name, undefined, undefined, undefined); 54 if (configure) configure(param); 55 this._parameters.push(param); 56 return this; 57 } 58 59 returns(returnType: string | py.Expression): this { 60 this._returnType = 61 typeof returnType === 'string' ? py.factory.createIdentifier(returnType) : returnType; 62 return this; 63 } 64 65 override toAst(): py.FunctionDeclaration { 66 this.$validate(); 67 return py.factory.createFunctionDeclaration( 68 this.name.toString(), 69 this._parameters, 70 this._returnType ? (this.$node(this._returnType) as py.Expression) : undefined, 71 this.$do(), 72 this.$decorators(), 73 this.$docs(), 74 this.modifiers, 75 ); 76 } 77 78 $validate(): asserts this { 79 const missing = this.missingRequiredCalls(); 80 if (missing.length === 0) return; 81 throw new Error(`Function declaration missing ${missing.join(' and ')}`); 82 } 83 84 private missingRequiredCalls(): ReadonlyArray<string> { 85 const missing: Array<string> = []; 86 if (!this.name.toString()) missing.push('name'); 87 return missing; 88 } 89}