Insert record constructors _inside_ Elm closure.

This commit is contained in:
Robin Heggelund Hansen 2021-08-20 08:41:27 +02:00
parent 4b8dbbed53
commit bf7663c69f
3 changed files with 26 additions and 8 deletions

View File

@ -10,9 +10,9 @@ export const recordUpdate = (): ts.TransformerFactory<ts.SourceFile> =>
const replacedLiterals = ts.visitNode(replacedUpdates, replaceObjectLiterals(propSet, registry, context));
const recordStatements = createRecordStatements(registry);
replacedLiterals.statements = recordStatements.concat(replacedLiterals.statements);
const insertedCtors = ts.visitNode(replacedLiterals, insertRecordConstructors(recordStatements, context));
return replacedLiterals;
return insertedCtors;
}
@ -37,7 +37,7 @@ class RecordRegistry {
const recordId = this.counter + 1;
this.counter = recordId;
const recordClassName = `Record${recordId}`;
const recordClassName = `$$Record${recordId}`;
this.map.set(shapeId, recordClassName);
@ -55,7 +55,7 @@ function replaceUpdateStatements(propSet: Set<String>, ctx: ts.TransformationCon
}
const objName = (updateExpression.arguments[0] as ts.Identifier).text;
const copyId = ts.createIdentifier('_r');
const copyId = ts.createIdentifier('$r');
const cloneObj = ts.createVariableStatement(
undefined,
@ -155,7 +155,7 @@ function isRecordLiteral(node: ts.Node): ts.ObjectLiteralExpression | null {
}
function createRecordStatements(registry: RecordRegistry): ts.NodeArray<ts.Statement> {
function createRecordStatements(registry: RecordRegistry): ts.Node[] {
const statementString = Array.from(registry.map.entries()).
map((it) => createRecordStatement(
it[1].valueOf(),
@ -184,3 +184,21 @@ function createRecordStatement(className: string, props: string[]): string {
}
`;
}
function insertRecordConstructors(ctors: ts.Node[], ctx: ts.TransformationContext) {
const visitorHelp = (node: ts.Node): ts.VisitResult<ts.Node> => {
if (isFirstFWrapper(node)) {
return ctors.concat(node);
}
return ts.visitEachChild(node, visitorHelp, ctx);
}
return visitorHelp;
}
function isFirstFWrapper(node: ts.Node): boolean {
return ts.isFunctionDeclaration(node) && node?.name?.text === 'F';
}

View File

@ -17,7 +17,7 @@ export const replace = (
const name = node.name;
if (name && isIdentifier(name) && name.text in replacements) {
const key = name.text as keyof typeof replacements;
return Array.from(astNodes(replacements[key]));
return astNodes(replacements[key]);
}
}
return ts.visitEachChild(node, visitor, context);

View File

@ -5,9 +5,9 @@ export const ast = (sourceText: string): ts.Node => {
return source.statements[0];
};
export const astNodes = (sourceText: string): ts.NodeArray<ts.Statement> => {
export const astNodes = (sourceText: string): ts.Node[] => {
const source = ts.createSourceFile('bla', sourceText, ts.ScriptTarget.ES2018);
return source.statements;
return Array.from(source.statements);
}
export function create(name: string, body: ts.Node): ts.Node {