mirror of
https://github.com/mdgriffith/elm-optimize-level-2.git
synced 2024-11-25 22:50:42 +03:00
Create and make use of record constructors instead of literal objects.
This commit is contained in:
parent
36e77be58a
commit
fddb3c41a3
@ -1,10 +1,16 @@
|
||||
import ts from 'typescript';
|
||||
import { astNodes } from './utils/create';
|
||||
|
||||
export const recordUpdate = (): ts.TransformerFactory<ts.SourceFile> =>
|
||||
(context) => (sourceFile) => {
|
||||
const registry = new RecordRegistry();
|
||||
ts.visitNode(sourceFile, replaceObjectLiterals(registry, context));
|
||||
return sourceFile;
|
||||
|
||||
const replacedLiterals = ts.visitNode(sourceFile, replaceObjectLiterals(registry, context));
|
||||
|
||||
const recordStatements = createRecordStatements(registry);
|
||||
replacedLiterals.statements = recordStatements.concat(replacedLiterals.statements);
|
||||
|
||||
return replacedLiterals;
|
||||
}
|
||||
|
||||
|
||||
@ -18,28 +24,91 @@ class RecordRegistry {
|
||||
}
|
||||
|
||||
register(recordAst: ts.Node): String {
|
||||
console.log(recordAst);
|
||||
const shapeId = recordAst.properties.
|
||||
map((it) => it.name.text).
|
||||
join(",");
|
||||
|
||||
if (this.map.has(shapeId)) {
|
||||
return this.map.get(shapeId);
|
||||
}
|
||||
|
||||
const recordId = this.counter + 1;
|
||||
this.counter = recordId;
|
||||
const recordClassName = `Record${recordId}`;
|
||||
|
||||
this.map.set(shapeId, recordClassName);
|
||||
|
||||
return recordClassName;
|
||||
}
|
||||
}
|
||||
|
||||
function replaceObjectLiterals(_registry: RecordRegistry, ctx: ts.TransformationContext) {
|
||||
function replaceObjectLiterals(registry: RecordRegistry, ctx: ts.TransformationContext) {
|
||||
const visitorHelp = (node: ts.Node): ts.VisitResult<ts.Node> => {
|
||||
if (isUpdateExpression(node)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
const visitedNode = ts.visitEachChild(node, visitorHelp, ctx);
|
||||
if (!isRecordLiteral(visitedNode)) {
|
||||
return visitedNode;
|
||||
}
|
||||
|
||||
const recordClassName = registry.register(visitedNode);
|
||||
console.log(recordClassName);
|
||||
const recordConstruction = ts.createParen(
|
||||
ts.createNew(
|
||||
ts.createIdentifier(recordClassName),
|
||||
undefined,
|
||||
visitedNode.properties.map((it) => it.initializer)
|
||||
)
|
||||
);
|
||||
|
||||
return visitedNode;
|
||||
return recordConstruction;
|
||||
}
|
||||
|
||||
return visitorHelp;
|
||||
}
|
||||
|
||||
function isUpdateExpression(node: ts.Node): boolean {
|
||||
return ts.isCallExpression(node) &&
|
||||
ts.isIdentifier(node.expression) &&
|
||||
node.expression.text === '_Utils_update';
|
||||
}
|
||||
|
||||
function isRecordLiteral(node: ts.Node): boolean {
|
||||
return ts.isObjectLiteralExpression(node) &&
|
||||
node.properties.length > 0 &&
|
||||
node.properties[0].name.text !== '$';
|
||||
}
|
||||
|
||||
|
||||
function createRecordStatements(registry: RecordRegistry): ts.Node[] {
|
||||
const statementString = Array.from(registry.map.entries()).
|
||||
map((it) => createRecordStatement(
|
||||
it[1],
|
||||
it[0].split(',')
|
||||
)).join('\n');
|
||||
|
||||
return astNodes(statementString);
|
||||
}
|
||||
|
||||
function createRecordStatement(className: String, props: String[]): String {
|
||||
const propList = props.join(',');
|
||||
const propSetters = props.
|
||||
map((name) => `this.${name} = ${name};`).
|
||||
join(' ');
|
||||
const propGetters = props.
|
||||
map((name) => `this.${name}`).
|
||||
join(', ');
|
||||
|
||||
return `
|
||||
function ${className}(${propList}) {
|
||||
${propSetters}
|
||||
}
|
||||
|
||||
${className}.prototype.$clone = function(cb) {
|
||||
var clone = new ${className}(${propGetters});
|
||||
cb(clone);
|
||||
return clone;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import ts from 'typescript';
|
||||
|
||||
export const ast = (sourceText: string): ts.Node => {
|
||||
|
Loading…
Reference in New Issue
Block a user