128a0f3faed4861767d82ddede43456cd7fc4bab
[platform/framework/web/crosswalk-tizen.git] /
1 "use strict";
2
3 var _tk = require('rocambole-token');
4 var _ws = require('rocambole-whitespace');
5 var debug = require('debug')('esformatter:parentheses');
6
7
8 exports.addSpaceInside = addSpaceInsideExpressionParentheses;
9 function addSpaceInsideExpressionParentheses(node) {
10   var parentheses = getParentheses(node);
11   if (parentheses) {
12     _ws.limitAfter(parentheses.opening, 'ExpressionOpeningParentheses');
13     _ws.limitBefore(parentheses.closing, 'ExpressionClosingParentheses');
14   }
15 }
16
17
18 exports.getParentheses = getParentheses;
19 function getParentheses(node) {
20   if (!isValidExpression(node)) {
21     debug('not valid expression: %s', node.type);
22     return;
23   }
24
25   var opening = node.startToken;
26   if (/^(?:Binary|Logical)Expression$/.test(node.type) || opening.value !== '(') {
27     opening = _tk.findPrevNonEmpty(opening);
28   }
29
30   if (!opening || opening.value !== '(') {
31     // "safe" to assume it is not inside parentheses
32     debug(
33       'opening is not a parentheses; type: %s, opening: "%s"',
34       node.type,
35       opening && opening.value
36     );
37     return;
38   }
39
40   var token = opening;
41   var count = 0;
42   var closing;
43
44   while(token) {
45     if (token.value === '(') {
46       count += 1;
47     } else if (token.value === ')') {
48       count -= 1;
49     }
50     if (count === 0) {
51       closing = token;
52       break;
53     }
54     token = token.next;
55   }
56
57   if (!closing) {
58     debug('not inside parentheses', count);
59     return;
60   }
61
62   debug(
63     'found parentheses; type: %s, opening: "%s", closing: "%s"',
64     node.type,
65     opening && opening.value,
66     closing && closing.value
67   );
68
69   return {
70     opening: opening,
71     closing: closing
72   };
73 }
74
75 // Literal when inside BinaryExpression might be surrounded by parenthesis
76 // CallExpression and ArrayExpression don't need spaces
77 var needExpressionParenthesesSpaces = {
78   Literal: true,
79   CallExpression: false,
80   FunctionExpression: false,
81   ArrayExpression: false,
82   ObjectExpression: false,
83   // Special is used when we need to override default behavior
84   Special: true
85 };
86
87
88 function isValidExpression(node) {
89   var needSpaces = needExpressionParenthesesSpaces[node.type];
90
91   if (needSpaces) {
92     return true;
93   }
94
95   if (needSpaces == null && node.type.indexOf('Expression') !== -1) {
96     if (node.type === 'ExpressionStatement' &&
97       (node.expression.callee && node.expression.callee.type === 'FunctionExpression')) {
98       // bypass IIFE
99       return false;
100     }
101     return true;
102   }
103
104   return false;
105 }
106