|
1 | 1 | import { Enum, Interface, Model, Operation, Union } from "@typespec/compiler";
|
2 | 2 | import {
|
3 |
| - AssetEmitter, |
4 | 3 | Context,
|
5 |
| - EmittedSourceFile, |
6 | 4 | EmitterOutput,
|
7 |
| - Scope, |
8 |
| - SourceFile, |
9 | 5 | TypeSpecDeclaration,
|
10 | 6 | createAssetEmitter,
|
11 | 7 | } from "@typespec/compiler/emitter-framework";
|
12 | 8 |
|
13 | 9 | import assert from "assert";
|
14 |
| -import * as prettier from "prettier"; |
15 | 10 | import { describe, it } from "vitest";
|
16 | 11 |
|
17 | 12 | import { SingleFileZodEmitter, ZodEmitter } from "../src/emitter.js";
|
18 |
| -import { EmitterOptions } from "../src/lib.js"; |
19 | 13 | import { emitTypeSpec, getHostForTypeSpecFile } from "./host.js";
|
20 | 14 |
|
21 | 15 | const testCode = `
|
@@ -534,106 +528,36 @@ describe("emitter-framework: zod emitter", () => {
|
534 | 528 | });
|
535 | 529 | });
|
536 | 530 |
|
537 |
| - it("emits to namespaces", async () => { |
538 |
| - const host = await getHostForTypeSpecFile(testCode); |
539 |
| - |
540 |
| - class NamespacedEmitter extends ZodEmitter { |
541 |
| - private nsByName: Map<string, Scope<string>> = new Map(); |
542 |
| - programContext(): Context { |
543 |
| - const outputFile = emitter.createSourceFile("output.ts"); |
544 |
| - return { |
545 |
| - scope: outputFile.globalScope, |
546 |
| - }; |
547 |
| - } |
548 |
| - |
549 |
| - modelDeclarationContext(model: Model): Context { |
550 |
| - const name = this.emitter.emitDeclarationName(model); |
551 |
| - if (!name) return {}; |
552 |
| - const nsName = name.slice(0, 1); |
553 |
| - let nsScope = this.nsByName.get(nsName); |
554 |
| - if (!nsScope) { |
555 |
| - nsScope = this.emitter.createScope( |
556 |
| - {}, |
557 |
| - nsName, |
558 |
| - this.emitter.getContext().scope |
559 |
| - ); |
560 |
| - this.nsByName.set(nsName, nsScope); |
561 |
| - } |
| 531 | + it("emits namespaces", async () => { |
| 532 | + const contents = await emitTypeSpecToTs(` |
| 533 | + namespace A; |
562 | 534 |
|
563 |
| - return { |
564 |
| - scope: nsScope, |
565 |
| - }; |
| 535 | + enum MyEnum { |
| 536 | + a: "hi"; |
| 537 | + b: "bye"; |
566 | 538 | }
|
567 | 539 |
|
568 |
| - async sourceFile( |
569 |
| - sourceFile: SourceFile<string> |
570 |
| - ): Promise<EmittedSourceFile> { |
571 |
| - const emittedSourceFile = await super.sourceFile(sourceFile); |
572 |
| - emittedSourceFile.contents += emitNamespaces(sourceFile.globalScope); |
573 |
| - emittedSourceFile.contents = await prettier.format( |
574 |
| - emittedSourceFile.contents, |
575 |
| - { |
576 |
| - parser: "typescript", |
| 540 | + namespace B { |
| 541 | + namespace C { |
| 542 | + model X { |
| 543 | + x: string; |
577 | 544 | }
|
578 |
| - ); |
579 |
| - return emittedSourceFile; |
580 |
| - |
581 |
| - function emitNamespaces(scope: Scope<string>) { |
582 |
| - let res = ""; |
583 |
| - for (const childScope of scope.childScopes) { |
584 |
| - res += emitNamespace(childScope); |
585 |
| - } |
586 |
| - return res; |
587 | 545 | }
|
588 |
| - function emitNamespace(scope: Scope<string>) { |
589 |
| - let ns = `export namespace ${scope.name} {\n`; |
590 |
| - ns += emitNamespaces(scope); |
591 |
| - for (const decl of scope.declarations) { |
592 |
| - ns += decl.value + ",\n"; |
593 |
| - } |
594 |
| - ns += `}\n`; |
| 546 | + op SomeOp(x: string): string; |
595 | 547 |
|
596 |
| - return ns; |
| 548 | + interface MyInterface { |
| 549 | + op get(): string; |
597 | 550 | }
|
598 | 551 | }
|
599 |
| - } |
600 |
| - const emitter = createAssetEmitter(host.program, NamespacedEmitter, { |
601 |
| - emitterOutputDir: host.program.compilerOptions.outputDir!, |
602 |
| - options: {}, |
603 |
| - } as any); |
604 |
| - emitter.emitProgram(); |
605 |
| - await emitter.writeOutput(); |
606 |
| - const contents = (await host.compilerHost.readFile("tsp-output/output.ts")) |
607 |
| - .text; |
608 |
| - |
609 |
| - assert.match(contents, /export namespace B \{/); |
610 |
| - assert.match(contents, /export namespace R \{/); |
611 |
| - assert.match(contents, /export namespace H \{/); |
612 |
| - assert.match(contents, /export namespace I \{/); |
613 |
| - assert.match(contents, /export namespace D \{/); |
614 |
| - assert.match(contents, /y: B\.BasicSchema/); |
615 |
| - assert.match(contents, /prop: B\.BasicSchema/); |
616 |
| - }); |
617 |
| - |
618 |
| - it("handles circular references", async () => { |
619 |
| - const host = await getHostForTypeSpecFile(` |
620 |
| - model Foo { prop: Baz } |
621 |
| - model Baz { prop: Foo } |
622 | 552 | `);
|
623 | 553 |
|
624 |
| - const emitter: AssetEmitter<string, EmitterOptions> = createAssetEmitter( |
625 |
| - host.program, |
626 |
| - SingleFileZodEmitter, |
627 |
| - { |
628 |
| - emitterOutputDir: host.program.compilerOptions.outputDir!, |
629 |
| - options: {}, |
630 |
| - } as any |
| 554 | + assert.match( |
| 555 | + contents, |
| 556 | + /export namespace A \{(\n|.)*export namespace B \{(\n|.)*export namespace C \{(\n|.)*\}(\n|.)*\}(\n|.)*\}/ |
| 557 | + ); |
| 558 | + assert.match( |
| 559 | + contents, |
| 560 | + /export namespace C \{(\n|.)*export const XSchema = z.object\((\n|.)*x: z.string\(\)(\n|.)*\)(\n|.)*\}/ |
631 | 561 | );
|
632 |
| - emitter.emitProgram(); |
633 |
| - await emitter.writeOutput(); |
634 |
| - const contents = (await host.compilerHost.readFile("tsp-output/output.ts")) |
635 |
| - .text; |
636 |
| - assert.match(contents, /prop: Foo/); |
637 |
| - assert.match(contents, /prop: Baz/); |
638 | 562 | });
|
639 | 563 | });
|
0 commit comments