Skip to content

Commit

Permalink
feat: Try alternate writer for for alt_serializer
Browse files Browse the repository at this point in the history
  • Loading branch information
runeh authored and simenandre committed Mar 25, 2021
1 parent 742ce62 commit 6543c99
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 65 deletions.
35 changes: 7 additions & 28 deletions src/__tests__/main_alt.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { format, resolveConfig } from 'prettier';
import { Project, SourceFile } from 'ts-morph';
import { generateRuntypes, groupFieldKinds } from '../main_alt';

async function fmt(source: string) {
Expand All @@ -8,18 +7,8 @@ async function fmt(source: string) {
}

describe('runtype generation', () => {
let project: Project;
let file: SourceFile;

beforeEach(() => {
project = new Project();
file = project.createSourceFile('./test.ts');
});

it('smoke test', async () => {
generateRuntypes(
file,

const raw = generateRuntypes(
{
name: 'personRt',
type: {
Expand Down Expand Up @@ -108,7 +97,6 @@ describe('runtype generation', () => {
},
},
);
const raw = file.getText();
const formatted = await fmt(raw);
expect(formatted).toMatchInlineSnapshot(`
"const personRt = rt
Expand All @@ -117,6 +105,7 @@ describe('runtype generation', () => {
age: rt.Number,
})
.asReadonly();
export const smokeTest = rt.Record({
someBoolean: rt.Boolean,
someNever: rt.Never,
Expand Down Expand Up @@ -177,15 +166,13 @@ describe('runtype generation', () => {
});

it('default modifiers', async () => {
generateRuntypes(file, {
const raw = generateRuntypes({
name: 'test',
type: {
kind: 'record',
fields: [{ name: 'name', type: { kind: 'string' } }],
},
});

const raw = file.getText();
const formatted = await fmt(raw);
expect(formatted).toMatchInlineSnapshot(`
"const test = rt.Record({
Expand All @@ -196,15 +183,13 @@ describe('runtype generation', () => {
});

it('readonly modifiers', async () => {
generateRuntypes(file, {
const raw = generateRuntypes({
name: 'test',
type: {
kind: 'record',
fields: [{ name: 'name', readonly: true, type: { kind: 'string' } }],
},
});

const raw = file.getText();
const formatted = await fmt(raw);
expect(formatted).toMatchInlineSnapshot(`
"const test = rt
Expand All @@ -217,15 +202,13 @@ describe('runtype generation', () => {
});

it('nullable modifiers', async () => {
generateRuntypes(file, {
const raw = generateRuntypes({
name: 'test',
type: {
kind: 'record',
fields: [{ name: 'name', nullable: true, type: { kind: 'string' } }],
},
});

const raw = file.getText();
const formatted = await fmt(raw);
expect(formatted).toMatchInlineSnapshot(`
"const test = rt
Expand All @@ -238,7 +221,7 @@ describe('runtype generation', () => {
});

it('both modifiers', async () => {
generateRuntypes(file, {
const raw = generateRuntypes({
name: 'test',
type: {
kind: 'record',
Expand All @@ -252,8 +235,6 @@ describe('runtype generation', () => {
],
},
});

const raw = file.getText();
const formatted = await fmt(raw);
expect(formatted).toMatchInlineSnapshot(`
"const test = rt
Expand All @@ -267,7 +248,7 @@ describe('runtype generation', () => {
});

it('all groups', async () => {
generateRuntypes(file, {
const raw = generateRuntypes({
name: 'test',
type: {
kind: 'record',
Expand Down Expand Up @@ -295,8 +276,6 @@ describe('runtype generation', () => {
],
},
});

const raw = file.getText();
const formatted = await fmt(raw);
expect(formatted).toMatchInlineSnapshot(`
"const test = rt.intersect(
Expand Down
88 changes: 51 additions & 37 deletions src/main_alt.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
import {
CodeBlockWriter,
OptionalKind,
SourceFile,
VariableDeclarationKind,
VariableStatementStructure,
} from 'ts-morph';
import {
AnyType,
ArrayType,
Expand All @@ -17,24 +10,45 @@ import {
UnionType,
} from './types_alt';

export function generateRuntypes(file: SourceFile, ...roots: RootType[]): void {
file.addVariableStatements(
roots.map<OptionalKind<VariableStatementStructure>>((root) => {
return {
isExported: root.export,
declarationKind: VariableDeclarationKind.Const,
declarations: [
{ name: root.name, initializer: (w) => writeAnyType(w, root.type) },
],
};
}),
);
interface CodeWriter {
getSource(): string;
write(data: string): void;
conditionalWrite(cond: boolean, data: string): void;
}

function makeWriter(): CodeWriter {
const chunks: string[] = [];
return {
getSource() {
return chunks.join('');
},
write(data) {
chunks.push(data);
},
conditionalWrite(cond, data) {
if (cond) {
chunks.push(data);
}
},
};
}

export function generateRuntypes(...roots: RootType[]): string {
const writer = makeWriter();
for (const root of roots) {
writer.conditionalWrite(Boolean(root.export), 'export ');
writer.write(`const ${root.name} = `);
writeAnyType(writer, root.type);
writer.write(';\n\n');
}

return writer.getSource();
}

// fixme: use mapped type so `node` is typed more narrowly maybe
const writers: Record<
AnyType['kind'],
(writer: CodeBlockWriter, node: AnyType) => void
(writer: CodeWriter, node: AnyType) => void
> = {
boolean: simpleWriter('rt.Boolean'),
function: simpleWriter('rt.Function'),
Expand All @@ -52,26 +66,26 @@ const writers: Record<
dictionary: writeDictionaryType,
};

function simpleWriter(value: string): (writer: CodeBlockWriter) => void {
function simpleWriter(value: string): (writer: CodeWriter) => void {
return (writer) => writer.write(value);
}

function writeDictionaryType(w: CodeBlockWriter, node: DictionaryType) {
function writeDictionaryType(w: CodeWriter, node: DictionaryType) {
w.write('rt.Dictionary(');
writeAnyType(w, node.valueType);
w.write(')');
}

function writeNamedType(w: CodeBlockWriter, node: NamedType) {
function writeNamedType(w: CodeWriter, node: NamedType) {
w.write(node.name);
}

function writeAnyType(w: CodeBlockWriter, node: AnyType) {
function writeAnyType(w: CodeWriter, node: AnyType) {
const writer = writers[node.kind];
writer(w, node);
}

function writeLiteralType(w: CodeBlockWriter, node: LiteralType) {
function writeLiteralType(w: CodeWriter, node: LiteralType) {
const { value } = node;
w.write('rt.Literal(');
if (value === undefined) {
Expand All @@ -87,29 +101,29 @@ function writeLiteralType(w: CodeBlockWriter, node: LiteralType) {
w.write(')');
}

function writeArrayType(w: CodeBlockWriter, node: ArrayType) {
function writeArrayType(w: CodeWriter, node: ArrayType) {
w.write('rt.Array(');
writeAnyType(w, node.type);
w.write(')');
w.conditionalWrite(node.readonly, '.asReadonly()');
}

function writeUnionType(w: CodeBlockWriter, node: UnionType) {
w.writeLine('rt.Union(');
function writeUnionType(w: CodeWriter, node: UnionType) {
w.write('\nrt.Union(');
for (const type of node.types) {
writeAnyType(w, type);
w.write(',\n');
}
w.writeLine(') ');
w.write('\n) ');
}

function writeIntersectionType(w: CodeBlockWriter, node: UnionType) {
w.writeLine('rt.Intersect(');
function writeIntersectionType(w: CodeWriter, node: UnionType) {
w.write('\nrt.Intersect(');
for (const type of node.types) {
writeAnyType(w, type);
w.write(',\n');
}
w.writeLine(') ');
w.write('\n) ');
}

/**
Expand Down Expand Up @@ -150,12 +164,12 @@ export function groupFieldKinds(
].filter((e) => e.fields.length > 0);
}

function writeRecordType(w: CodeBlockWriter, node: RecordType) {
function writeRecordType(w: CodeWriter, node: RecordType) {
const fieldKinds = groupFieldKinds(node.fields);
const hasMultiple = fieldKinds.length > 1;
w.conditionalWriteLine(hasMultiple, 'rt.intersect(');
w.conditionalWrite(hasMultiple, '\nrt.intersect(');
for (const fieldKind of fieldKinds) {
w.writeLine('rt.Record({');
w.write('rt.Record({\n');
for (const field of fieldKind.fields) {
w.write(field.name);
w.write(': ');
Expand All @@ -165,7 +179,7 @@ function writeRecordType(w: CodeBlockWriter, node: RecordType) {
w.write('})');
w.conditionalWrite(fieldKind.nullable ?? false, '.asPartial()');
w.conditionalWrite(fieldKind.readonly ?? false, '.asReadonly()');
w.conditionalWriteLine(hasMultiple, ',');
w.conditionalWrite(hasMultiple, '\n,');
}
w.conditionalWriteLine(hasMultiple, ')');
w.conditionalWrite(hasMultiple, '\n)');
}

0 comments on commit 6543c99

Please sign in to comment.