120 lines
2.7 KiB
JavaScript
120 lines
2.7 KiB
JavaScript
import template from "babel-template";
|
|
import explodeClass from "babel-helper-explode-class";
|
|
|
|
let buildClassDecorator = template(`
|
|
CLASS_REF = DECORATOR(CLASS_REF) || CLASS_REF;
|
|
`);
|
|
|
|
export default function ({ types: t }) {
|
|
function cleanDecorators(decorators) {
|
|
return decorators.reverse().map((dec) => dec.expression);
|
|
}
|
|
|
|
function transformClass(path, ref, state) {
|
|
let nodes = [];
|
|
|
|
state;
|
|
|
|
let classDecorators = path.node.decorators;
|
|
if (classDecorators) {
|
|
path.node.decorators = null;
|
|
classDecorators = cleanDecorators(classDecorators);
|
|
|
|
for (let decorator of classDecorators) {
|
|
nodes.push(buildClassDecorator({
|
|
CLASS_REF: ref,
|
|
DECORATOR: decorator
|
|
}));
|
|
}
|
|
}
|
|
|
|
let map = Object.create(null);
|
|
|
|
for (let method of path.get("body.body")) {
|
|
let decorators = method.node.decorators;
|
|
if (!decorators) continue;
|
|
|
|
let alias = t.toKeyAlias(method.node);
|
|
map[alias] = map[alias] || [];
|
|
map[alias].push(method.node);
|
|
|
|
method.remove();
|
|
}
|
|
|
|
for (let alias in map) {
|
|
let items = map[alias];
|
|
|
|
items;
|
|
}
|
|
|
|
return nodes;
|
|
}
|
|
|
|
function hasDecorators(path) {
|
|
if (path.isClass()) {
|
|
if (path.node.decorators) return true;
|
|
|
|
for (let method of path.node.body.body) {
|
|
if (method.decorators) {
|
|
return true;
|
|
}
|
|
}
|
|
} else if (path.isObjectExpression()) {
|
|
for (let prop of path.node.properties) {
|
|
if (prop.decorators) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function doError(path) {
|
|
throw path.buildCodeFrameError("Decorators are not supported yet in 6.x pending proposal update.");
|
|
}
|
|
|
|
return {
|
|
inherits: require("babel-plugin-syntax-decorators"),
|
|
|
|
visitor: {
|
|
ClassExpression(path) {
|
|
if (!hasDecorators(path)) return;
|
|
doError(path);
|
|
|
|
explodeClass(path);
|
|
|
|
let ref = path.scope.generateDeclaredUidIdentifier("ref");
|
|
let nodes = [];
|
|
|
|
nodes.push(t.assignmentExpression("=", ref, path.node));
|
|
|
|
nodes = nodes.concat(transformClass(path, ref, this));
|
|
|
|
nodes.push(ref);
|
|
|
|
path.replaceWith(t.sequenceExpression(nodes));
|
|
},
|
|
|
|
ClassDeclaration(path) {
|
|
if (!hasDecorators(path)) return;
|
|
doError(path);
|
|
explodeClass(path);
|
|
|
|
let ref = path.node.id;
|
|
let nodes = [];
|
|
|
|
nodes = nodes.concat(transformClass(path, ref, this).map((expr) => t.expressionStatement(expr)));
|
|
nodes.push(t.expressionStatement(ref));
|
|
|
|
path.insertAfter(nodes);
|
|
},
|
|
|
|
ObjectExpression(path) {
|
|
if (!hasDecorators(path)) return;
|
|
doError(path);
|
|
}
|
|
}
|
|
};
|
|
}
|