@putout/printer 1.73.2 → 1.75.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ChangeLog CHANGED
@@ -1,3 +1,13 @@
1
+ 2023.04.27, v1.75.0
2
+
3
+ feature:
4
+ - 0560c33 @putout/printer: MemberExpression: simplify chain
5
+
6
+ 2023.04.26, v1.74.0
7
+
8
+ feature:
9
+ - 9ef7aaa @putout/printer: add support of empty value in JSXAttribute
10
+
1
11
  2023.04.26, v1.73.2
2
12
 
3
13
  feature:
package/README.md CHANGED
@@ -51,7 +51,6 @@ const {parse} = require('@babel/parser');
51
51
  const ast = parse('const a = (b, c) => {const d = 5; return a;}');
52
52
 
53
53
  print(ast);
54
-
55
54
  // returns
56
55
  `
57
56
  const a = (b, c) => {
@@ -87,7 +86,6 @@ print(ast, {
87
86
  },
88
87
  },
89
88
  });
90
-
91
89
  // returns
92
90
  'const {a /* [hello world] */= 5} = b;\n';
93
91
  ```
@@ -22,8 +22,6 @@ const isStringAndString = ([a, b]) => isStringLiteral(a) && isStringLiteral(b);
22
22
  const isIdentifierAndIdentifier = ([a, b]) => isIdentifier(a) && isIdentifier(b);
23
23
  const isArrayParent = (path) => path.parentPath.isArrayExpression();
24
24
 
25
- const isTwoElementReturn = (path, {elements}) => path.parentPath.isReturnStatement() && elements.length === 2;
26
-
27
25
  const isTwoLongStrings = ([a, b]) => {
28
26
  const LONG_STRING = 20;
29
27
 
@@ -207,10 +205,10 @@ function isNewlineBetweenElements(path, {elements}) {
207
205
  if (isOneSimple(path))
208
206
  return false;
209
207
 
210
- if (isCallInsideArrow(path))
208
+ if (elements.length === 2 && isIdentifierAndIdentifier(elements))
211
209
  return false;
212
210
 
213
- if (isTwoElementReturn(path, {elements}))
211
+ if (isCallInsideArrow(path))
214
212
  return false;
215
213
 
216
214
  if (isOneElementCall(path, {elements}))
@@ -0,0 +1,75 @@
1
+ 'use strict';
2
+
3
+ const {assign} = Object;
4
+
5
+ module.exports.chain = (path) => {
6
+ const all = [
7
+ ...down(path),
8
+ ...up(path),
9
+ ];
10
+
11
+ const properties = all.slice(0, -1);
12
+ const root = all.at(-1);
13
+
14
+ return [root, properties];
15
+ };
16
+
17
+ function down(path) {
18
+ const properties = [];
19
+
20
+ let current = path.get('object');
21
+
22
+ while (!current.isIdentifier()) {
23
+ const isFn = current.isCallExpression();
24
+ const prop = build(current);
25
+
26
+ if (isFn)
27
+ current = current.get('callee');
28
+
29
+ properties.unshift(prop);
30
+
31
+ if (!current.isMemberExpression())
32
+ break;
33
+
34
+ current = current.get('object');
35
+ }
36
+
37
+ return properties;
38
+ }
39
+
40
+ function up(current) {
41
+ const properties = [];
42
+
43
+ while (current.isMemberExpression()) {
44
+ current = current.parentPath;
45
+
46
+ if (current.isCallExpression()) {
47
+ properties.push(build(current));
48
+ current = current.parentPath;
49
+ }
50
+
51
+ if (!current.isMemberExpression())
52
+ break;
53
+ }
54
+
55
+ properties.push({
56
+ type: current.type,
57
+ });
58
+
59
+ return properties;
60
+ }
61
+
62
+ function build(path) {
63
+ const prop = {
64
+ type: path.type,
65
+ };
66
+
67
+ if (path.isCallExpression()) {
68
+ assign(prop, {
69
+ args: path.node.arguments.length,
70
+ name: path.node.callee.property?.name || '',
71
+ });
72
+ }
73
+
74
+ return prop;
75
+ }
@@ -1,18 +1,14 @@
1
1
  'use strict';
2
2
 
3
3
  const {
4
- isIfStatement,
5
- isIdentifier,
6
- isThisExpression,
7
4
  isUnaryExpression,
5
+ isArrowFunctionExpression,
6
+ isLogicalExpression,
8
7
  } = require('@babel/types');
9
8
 
10
- const {
11
- compare,
12
- getTemplateValues,
13
- } = require('@putout/compare');
9
+ const {chain} = require('./chain/chain');
14
10
 
15
- module.exports.MemberExpression = (path, {print, indent, maybe, traverse}) => {
11
+ module.exports.MemberExpression = (path, {print, maybe, traverse}) => {
16
12
  const {computed} = path.node;
17
13
  const object = path.get('object');
18
14
  const isObjectAwait = object.isAwaitExpression();
@@ -29,12 +25,12 @@ module.exports.MemberExpression = (path, {print, indent, maybe, traverse}) => {
29
25
  return;
30
26
  }
31
27
 
32
- const isChain = isLooksLikeChain(path);
28
+ const isChain = likeChain(path);
29
+
33
30
  maybe.indent.inc(isChain);
34
31
 
35
32
  if (isChain) {
36
- print.newline();
37
- indent(isChain);
33
+ print.breakline();
38
34
  }
39
35
 
40
36
  print('.');
@@ -58,66 +54,25 @@ module.exports.OptionalMemberExpression = (path, {print}) => {
58
54
  print('__property');
59
55
  };
60
56
 
61
- function isLooksLikeChain(path) {
62
- const {parentPath} = path;
63
-
64
- if (path.find(isIfStatement))
65
- return false;
66
-
67
- if (compare(parentPath.parentPath.parentPath, '__a.__b(__x).__c(__y)'))
68
- return true;
69
-
70
- if (compare(parentPath, '__a.__b(__x).__c(__y)'))
71
- return true;
72
-
73
- if (path.find(isUnaryExpression))
74
- return false;
75
-
76
- const isMember = ({parentPath}) => parentPath.parentPath.isMemberExpression();
77
- const isExpression = ({parentPath}) => parentPath.parentPath.isExpressionStatement();
78
- const itMember = isMember(path);
79
- const itExpression = isExpression(path);
80
- const callee = parentPath.get('callee');
81
-
82
- if (parentPath.isLiteral())
83
- return false;
84
-
85
- if (!itMember && !path.parentPath.isExpressionStatement() && !parentPath.isCallExpression())
86
- return false;
87
-
88
- if (!parentPath.isCallExpression())
89
- return false;
90
-
91
- if (callee !== path)
92
- return false;
93
-
94
- if (compare(path.parentPath, '__a.__b(__args)[__c]'))
95
- return false;
96
-
97
- if (compare(path.parentPath.parentPath, '__a.__b().__c()'))
98
- return false;
99
-
100
- if (compare(path.parentPath.parentPath, '(__args) => __b.__c(__args).__d()'))
101
- return false;
57
+ const isCall = (a) => a.type === 'CallExpression';
58
+
59
+ function likeChain(path) {
60
+ const [root, properties] = chain(path);
102
61
 
103
- if (compare(parentPath, '__a.__b.__c(__args)') && !itMember)
62
+ if (isUnaryExpression(root))
104
63
  return false;
105
64
 
106
- if (compare(parentPath, '__a.__b.__c = __d'))
65
+ if (isArrowFunctionExpression(root))
107
66
  return false;
108
67
 
109
- if (compare(parentPath, '(__args) => __a.__b(__args).__c'))
68
+ if (isLogicalExpression(root))
110
69
  return false;
111
70
 
112
- const {__a, __b} = getTemplateValues(parentPath, '__a.__b(__args)');
113
- const aType = __a?.type;
114
- const bType = __b?.type;
115
-
116
- if (aType === bType && isIdentifier(__a) && itExpression)
117
- return false;
71
+ const calls = properties.filter(isCall);
72
+ const [firstCall] = calls;
118
73
 
119
- if (isThisExpression(__a) && isIdentifier(__b) && itExpression)
74
+ if (calls.length === 2 && !firstCall.name)
120
75
  return false;
121
76
 
122
- return itExpression;
77
+ return calls.length > 1;
123
78
  }
@@ -10,9 +10,11 @@ module.exports.JSXAttribute = {
10
10
  indent.inc();
11
11
  print.breakline();
12
12
  },
13
- print(path, {print}) {
13
+ print(path, {print, maybe}) {
14
+ const {value} = path.node;
15
+
14
16
  print('__name');
15
- print('=');
17
+ maybe.print(value, '=');
16
18
  print('__value');
17
19
  },
18
20
  after(path, {indent}) {
@@ -15,6 +15,9 @@ const isNextLiteral = (path) => {
15
15
  const next = path.getNextSibling();
16
16
  const expression = next.get('expression');
17
17
 
18
+ if (expression.isTemplateLiteral())
19
+ return true;
20
+
18
21
  return expression.isLiteral();
19
22
  };
20
23
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@putout/printer",
3
- "version": "1.73.2",
3
+ "version": "1.75.0",
4
4
  "type": "commonjs",
5
5
  "author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
6
6
  "description": "Simplest possible opinionated Babel AST printer fro 🐊Putout",