UNPKG

2.96 kBJavaScriptView Raw
1const ASTCreator = require('./utils/ASTCreator')
2
3class ASTTransformer {
4 constructor (ctx) {
5 this.__transformers = {}
6 this.ctx = ctx
7 }
8
9 add (type, fn) {
10 if (!this.__transformers[type]) {
11 this.__transformers[type] = []
12 }
13
14 this.__transformers[type].push(fn)
15 }
16
17 get (type) {
18 return this.__transformers[type] || null
19 }
20
21 load (dirName) {
22 const transformations = [
23 'classDeclaration',
24 'exportAllDeclaration',
25 'exportDeclaration',
26 'functionDeclaration',
27 'functionExpression',
28 'functionParamTyping',
29 'importDeclaration',
30 'logStatement',
31 'programm',
32 'regexp',
33 'templateLiteral',
34 'variableTyping'
35 ]
36
37 transformations.forEach((t) => {
38 const fn = require(`./${dirName}/${t}.js`)
39 fn(this)
40 })
41 }
42
43 test (fn) {
44 return fn(this.ctx)
45 }
46
47 transform (ast) {
48 const transformatedAst = this.transformItem(ast)
49 if (this.importRuntime && this.ctx.dissableRuntime !== true) {
50 this.importModule([[ 'FirescriptRuntime' ]], this.ctx.fireRTModuleName || 'firescript-runtime', transformatedAst)
51 }
52
53 return transformatedAst
54 }
55
56 transformItem (ast, index, parent) {
57 const transformatedAst = {}
58 if (ast.FS_skipTransform) {
59 return ast.FS_skipTransform
60 }
61
62 const transformationFn = (funcs, ast) => {
63 let trans = ast
64 funcs.forEach((fn) => {
65 trans = Array.isArray(trans)
66 ? trans.map(fn)
67 : fn(trans)
68 })
69
70 return trans
71 }
72
73 const funcs = this.get(ast.type)
74 if (funcs) {
75 const transformed = transformationFn(funcs, ast)
76 if (Array.isArray(transformed)) {
77 return transformed
78 } else if (transformed !== ast) {
79 ast = transformed
80 }
81 }
82
83 const keys = Object.keys(ast)
84 for (const key of keys) {
85 if (Array.isArray(ast[key])) {
86 const childs = []
87 ast[key].forEach((item, index, parent) => {
88 if (item && typeof item === 'object') {
89 const transformed = this.transformItem(item, index, parent)
90 if (Array.isArray(transformed)) {
91 transformed.forEach((child) => childs.push(this.transformItem(child)))
92 } else {
93 childs.push(transformed)
94 }
95 } else {
96 childs.push(item)
97 }
98 })
99 transformatedAst[key] = childs
100 } else if (typeof ast[key] === 'object' && ast[key] !== null) {
101 transformatedAst[key] = this.transformItem(ast[key])
102 } else {
103 transformatedAst[key] = ast[key]
104 }
105 }
106
107 return transformatedAst
108 }
109
110 importModule (specifiers, moduleName, ast) {
111 const importDeclaration = ASTCreator.importDeclaration(specifiers, moduleName)
112
113 const runtimeImport = this.transformItem(importDeclaration)
114 ast.body.unshift(Array.isArray(runtimeImport) ? runtimeImport[0] : runtimeImport)
115 }
116}
117
118module.exports = ASTTransformer