1 | 'use strict';
|
2 |
|
3 | const path = require('path');
|
4 | const Macros = require('./utils/macros');
|
5 | const normalizeOptions = require('./utils/normalize-options').normalizeOptions;
|
6 |
|
7 | function macros(babel) {
|
8 | let t = babel.types;
|
9 |
|
10 | function buildIdentifier(value, name) {
|
11 | let replacement = t.booleanLiteral(value);
|
12 |
|
13 |
|
14 |
|
15 | let comment = {
|
16 | type: 'CommentBlock',
|
17 | value: ` ${name} `,
|
18 | leading: false,
|
19 | trailing: true,
|
20 | };
|
21 | replacement.trailingComments = [comment];
|
22 |
|
23 | return replacement;
|
24 | }
|
25 |
|
26 | return {
|
27 | name: 'babel-feature-flags-and-debug-macros',
|
28 | visitor: {
|
29 | ImportSpecifier(path, state) {
|
30 | let importPath = path.parent.source.value;
|
31 | let flagsForImport = state.opts.flags[importPath];
|
32 |
|
33 | if (flagsForImport) {
|
34 | let flagName = path.node.imported.name;
|
35 | let localBindingName = path.node.local.name;
|
36 |
|
37 | if (!(flagName in flagsForImport)) {
|
38 | throw new Error(
|
39 | `Imported ${flagName} from ${importPath} which is not a supported flag.`
|
40 | );
|
41 | }
|
42 |
|
43 | let flagValue = flagsForImport[flagName];
|
44 | if (flagValue === null) {
|
45 | return;
|
46 | }
|
47 |
|
48 | let binding = path.scope.getBinding(localBindingName);
|
49 |
|
50 | binding.referencePaths.forEach(p => {
|
51 | p.replaceWith(buildIdentifier(flagValue, flagName));
|
52 | });
|
53 |
|
54 | path.remove();
|
55 | path.scope.removeOwnBinding(localBindingName);
|
56 | }
|
57 | },
|
58 |
|
59 | ImportDeclaration: {
|
60 | exit(path, state) {
|
61 | let importPath = path.node.source.value;
|
62 | let flagsForImport = state.opts.flags[importPath];
|
63 |
|
64 |
|
65 | if (flagsForImport && path.get('specifiers').length === 0) {
|
66 | path.remove();
|
67 | }
|
68 | },
|
69 | },
|
70 |
|
71 | Program: {
|
72 | enter(path, state) {
|
73 | state.opts = normalizeOptions(state.opts);
|
74 | this.macroBuilder = new Macros(babel, state.opts);
|
75 |
|
76 | let body = path.get('body');
|
77 |
|
78 | body.forEach(item => {
|
79 | if (item.isImportDeclaration()) {
|
80 | let importPath = item.node.source.value;
|
81 |
|
82 | let debugToolsImport = state.opts.debugTools.debugToolsImport;
|
83 |
|
84 | if (debugToolsImport && debugToolsImport === importPath) {
|
85 | if (!item.node.specifiers.length) {
|
86 | item.remove();
|
87 | } else {
|
88 | this.macroBuilder.collectDebugToolsSpecifiers(item.get('specifiers'));
|
89 | }
|
90 | }
|
91 | }
|
92 | });
|
93 | },
|
94 |
|
95 | exit(path) {
|
96 | this.macroBuilder.expand(path);
|
97 | },
|
98 | },
|
99 |
|
100 | ExpressionStatement(path) {
|
101 | this.macroBuilder.build(path);
|
102 | },
|
103 | },
|
104 | };
|
105 | }
|
106 |
|
107 | macros.baseDir = function() {
|
108 | return path.dirname(__dirname);
|
109 | };
|
110 |
|
111 | module.exports = macros;
|