gogoast
Version:
The simplest tool to parse/transform/generate code by ast
102 lines (96 loc) • 3.45 kB
JavaScript
// 把简单的api转换成ast
const recast = require('recast');
const parse = require('./parse');
const visit = recast.types.visit;
const filterProps = require('./filter-prop.js');
// function parse(str) {
// let ast = null;
// try {
// ast = recast.parse(selectorCode)
// } catch (e) {
// if (str.split(' ')[0] == 'return') {
// const content = recast.parse(str.slice(6));
// // return 语句
// return parseReturn(content);
// }
// }
// return ast;
// }
// function parseReturn(content) {
// return builders.Program(
// builders.ExpressionStatement(
// builders.BlockStatement(
// builders.returnStatement(builders.identifier(promiseVarName))
// )
// )
// )
// }
function getSelector(selectorCode, parseOptions) {
const selector = { nodeType: '', structure: {} };
if (typeof selectorCode != 'string') {
// 如果是通过builders造出来的ast结构,比如return语句
selector.nodeType = selectorCode.type;
filterProps(selectorCode, selector.structure);
selector.type = selectorCode.type; // 兼容只用type匹配的选择器
return selector;
}
if (selectorCode.match(/^{((.|\s)+:(.|\s)+)+}$/)) {
// 如果是对象字面量
let ast = parse(`var o = ${selectorCode}`);
ast = ast.program.body[0].declarations[0].init;
selector.nodeType = 'ObjectExpression';
filterProps(ast, selector.structure);
return selector;
}
let seletorAst = parse(selectorCode, parseOptions);
if (seletorAst.program.body.length == 0) {
// 开头的字符串会被解析成directive
return {
nodeType: 'StringLiteral',
structure: {
value: selectorCode.slice(1, -1)
}
}
}
visit(seletorAst, {
visitExpressionStatement(path) {
const expression = path.value.expression;
selector.nodeType = expression.type;
if (!expression) return;
filterProps(expression, selector.structure);
this.abort();
},
visitVariableDeclaration(path) {
// 目前不考虑选择器有 var a = 1, b = 2这种 TODO
// const declaration = path.value.declarations[0];
const declaration = path.value
selector.nodeType = declaration.type;
if (!declaration) return;
filterProps(declaration, selector.structure);
this.abort();
},
visitImportDeclaration(path) {
const declaration = path.value;
selector.nodeType = declaration.type;
if (!declaration) return;
filterProps(declaration, selector.structure);
this.abort();
},
visitClassDeclaration(path) {
const declaration = path.value;
selector.nodeType = declaration.type;
if (!declaration) return;
filterProps(declaration, selector.structure);
this.abort();
},
visitDeclaration(path) {
const declaration = path.value;
selector.nodeType = declaration.type;
if (!declaration) return;
filterProps(declaration, selector.structure);
this.abort();
}
});
return selector;
}
module.exports = getSelector;