UNPKG

3.5 kBJavaScriptView Raw
1import {isElement} from './ast';
2import generate from './generation';
3
4
5const add = (set, key) => set[key] = true;
6const del = (set, key) => delete set[key];
7
8export default function freeVariablesInMessage(node) {
9 if (!isElement(node)) {
10 return [];
11 }
12 const variables = {};
13 freeVariablesInChildren(node.children, variables);
14 del(variables, 'this');
15 return Object.keys(variables);
16}
17
18function freeVariablesInChildren(children, variables) {
19 children.forEach(child => {
20 switch(child.type) {
21 case 'JSXElement':
22 freeVariablesInElement(child, variables);
23 break;
24
25 case 'JSXExpressionContainer':
26 freeVariablesInExpression(child.expression, variables);
27 break;
28 }
29 });
30}
31
32function freeVariablesInElement(element, variables) {
33 freeVariablesInElementName(element.openingElement.name, variables);
34 freeVariablesInAttributes(element.openingElement.attributes, variables);
35 freeVariablesInChildren(element.children, variables);
36}
37
38function freeVariablesInElementName(name, variables) {
39 if (name.type === 'JSXIdentifier') {
40 if (name.name.toLowerCase() !== name.name) {
41 add(variables, name.name);
42 }
43 } else if (name.type === 'JSXMemberExpression') {
44 // FIXME
45 add(variables, generate(name).split('.')[0]);
46 } else if (name.type === 'JSXNamespacedName') {
47 if (name.namespace.name.toLowerCase() !== name.namespace.name) {
48 add(variables, name.namespace.name);
49 }
50 }
51}
52
53function freeVariablesInAttributes(attributes, variables) {
54 attributes.forEach(a => freeVariablesInAttribute(a, variables));
55}
56
57function freeVariablesInAttribute(attribute, variables) {
58 if (
59 attribute.value &&
60 attribute.value.type === 'JSXExpressionContainer'
61 ) {
62 freeVariablesInExpression(attribute.value.expression, variables);
63 }
64 if (
65 attribute.type === 'JSXSpreadAttribute'
66 ) {
67 freeVariablesInExpression(attribute.argument, variables);
68 }
69}
70
71function freeVariablesInObjectExpression(expression, variables) {
72 expression.properties.forEach(property => {
73 if (property.type === 'SpreadProperty') {
74 freeVariablesInExpression(property.argument, variables);
75 } else {
76 freeVariablesInExpression(property.value, variables);
77 if (property.computed) {
78 freeVariablesInExpression(property.key, variables);
79 }
80 }
81 });
82}
83
84function freeVariablesInExpression(expression, variables) {
85 switch(expression.type) {
86 case 'Identifier':
87 add(variables, expression.name);
88 break;
89
90 case 'MemberExpression':
91 add(variables, generate(expression).split('.')[0]);
92 break;
93
94 case 'CallExpression':
95 freeVariablesInExpression(expression.callee, variables);
96 break;
97
98 case 'BinaryExpression':
99 freeVariablesInExpression(expression.left, variables);
100 freeVariablesInExpression(expression.right, variables);
101 break;
102
103 case 'ObjectExpression':
104 freeVariablesInObjectExpression(expression, variables);
105 break;
106
107 case 'Literal':
108 case 'StringLiteral':
109 case 'NumericLiteral':
110 case 'BooleanLiteral':
111 case 'JSXEmptyExpression':
112 // noop
113 break;
114
115 default:
116 console.log(expression);
117 }
118}