2016-03-01 22:33:30 -08:00

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);
}
}
};
}