Skip to content

Instantly share code, notes, and snippets.

@a-x-
Created February 9, 2019 20:29
Show Gist options
  • Save a-x-/adc99a6c115a2df67adade6250fca81a to your computer and use it in GitHub Desktop.
Save a-x-/adc99a6c115a2df67adade6250fca81a to your computer and use it in GitHub Desktop.
rm initClass AST based post-processor for decaffeinate
#!/usr/bin/env node
// fixes the decaffeinate result: rm all the static initClass functions
// node scripts/coffee2es6jsx/rm-initClass.mjs files
// todo: rm Search.initClass();
const fs = require('fs');
const Glob = require('glob');
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;
// const template = require("@babel/template").default; // quasiquotes
const generate = require("@babel/generator").default;
const t = require("@babel/types");
const read = name => fs.readFileSync(name, 'utf8')
const glob = (glob, each) => Glob(glob, (err, files) => files && files.filter(file => file).map(each))
const createClassProp = (nameNode, valNode, { isStatic } = {}) => {
return {
...t.classProperty(nameNode, valNode),
static: isStatic,
}
}
function findAst(globPattern) {
glob(globPattern, file => {
const code = read(file)
const ast = parser.parse(code, {
// locations: true,
// allowHashBang: true,
sourceType: "module",
plugins: ["jsx", 'optionalChaining', 'classProperties'],
})
traverse(ast, {
ClassMethod(path) {
const { node } = path;
if (!(node.static && node.key.name === 'initClass')) return;
const { body } = node.body
const items = body
.filter(item => {
if (!(item.type === 'ExpressionStatement' && item.expression.type === 'AssignmentExpression')) return false;
const assgn = item.expression.left;
if (!(assgn.type === 'MemberExpression')) return false;
return true;
})
.map((item) => {
const assgn = item.expression.left;
// (this.prototype).smth = ... -> static smth = ...
const { name } = assgn.property;
const valueNode = item.expression.right;
if (assgn.object.type === 'MemberExpression' && assgn.object.property.name === 'prototype') {
return createClassProp(t.identifier(name), valueNode);
}
// this.smth = ... -> smth = ...
else {
return createClassProp(t.identifier(name), valueNode, { isStatic: true });
}
});
path.replaceWithMultiple(items);
}
});
process.stdout.write(generate(ast).code);
})
}
findAst(process.argv[2])
/*
//
// RAW:
static initClass() {
this.propTypes =
{onChange: PropTypes.func.isRequired};
this.prototype.state = {
term: "",
results: null,
inProgress: false,
resetTermHack: null,
qrInputMode: 'input'
};
this.prototype.url = "/admin/package_creations/search_card";
}
*/
/*
//
// Target:
static propTypes = {onChange: PropTypes.func.isRequired};
state = {
term: "",
results: null,
inProgress: false,
resetTermHack: null,
qrInputMode: 'input'
}
url = "/admin/package_creations/search_card"
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment