diff --git a/type-generation/src/astToIR.ts b/type-generation/src/astToIR.ts index 7c09346..6f239fc 100644 --- a/type-generation/src/astToIR.ts +++ b/type-generation/src/astToIR.ts @@ -754,9 +754,12 @@ export class Converter { for (const param of decl.getParameters()) { const spread = !!param.getDotDotDotToken(); const optional = !!param.hasQuestionToken(); + const name = param.getName(); + this.pushNameContext(name); const type = this.typeToIR(param.getTypeNode()!, optional); + this.popNameContext(); const pyParam: ParamIR = { - name: param.getName(), + name, type, isOptional: optional, }; @@ -896,7 +899,14 @@ export class Converter { signatures: Signature[], isStatic?: boolean, ): CallableIR { - const sigs = signatures.flatMap((sig) => this.sigToIRDestructure(sig)); + this.pushNameContext(name); + const sigs = signatures.flatMap((sig, idx) => { + this.pushNameContext(`Sig${idx}`); + const result = this.sigToIRDestructure(sig); + this.popNameContext(); + return result; + }); + this.popNameContext(); const result: CallableIR = { kind: "callable", @@ -1091,25 +1101,25 @@ export class Converter { const typeArgs = typeParams.map((param) => simpleType(param)); const concreteBases = [{ name: ifaceName, typeArgs }]; const constructors = classDecl.getConstructors(); - - return [ - this.interfaceToIR( - ifaceName, - bases, - [...methods, ...properties], - [], - [], - typeParams, - ), - this.interfaceToIR( - name, - concreteBases, - [], - [...constructors, ...staticMethods, ...staticProperties], - [], - typeParams, - ), - ]; + this.nameContext = [name]; + const ifaceIR = this.interfaceToIR( + ifaceName, + bases, + [...methods, ...properties], + [], + [], + typeParams, + ); + const concreteIR = this.interfaceToIR( + name, + concreteBases, + [], + [...constructors, ...staticMethods, ...staticProperties], + [], + typeParams, + ); + this.nameContext = undefined; + return [ifaceIR, concreteIR]; } getBasesOfDecls( diff --git a/type-generation/tests/a.test.ts b/type-generation/tests/a.test.ts index de8c877..559c4a9 100644 --- a/type-generation/tests/a.test.ts +++ b/type-generation/tests/a.test.ts @@ -1797,6 +1797,50 @@ describe("emit", () => { `).trim(), ); }); + describe("type literals", () => { + it("type literal in class property", () => { + const res = emitFile(` + declare class T { + a: {x: string, y: boolean}; + } + `); + assert.strictEqual( + removeTypeIgnores(res.slice(1).join("\n\n")), + dedent(` + class T_iface(Protocol): + a: T__a_iface = ... + + class T(T_iface, _JsObject): + pass + + class T__a_iface(Protocol): + x: str = ... + y: bool = ... + `).trim(), + ); + }); + it("type literal in class method signature", () => { + const res = emitFile(` + declare class T { + f(a: {x: string, y: boolean}, b: boolean): void; + } + `); + assert.strictEqual( + removeTypeIgnores(res.slice(1).join("\n\n")), + dedent(` + class T_iface(Protocol): + def f(self, a: T__f__Sig0__a_iface, b: bool, /) -> None: ... + + class T(T_iface, _JsObject): + pass + + class T__f__Sig0__a_iface(Protocol): + x: str = ... + y: bool = ... + `).trim(), + ); + }); + }); describe("adjustments", () => { it("setTimeout", () => { const res = emitIRNoTypeIgnores(convertBuiltinFunction("setTimeout"));