@putout/printer 1.74.0 → 1.76.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 +10 -0
- package/lib/tokenize/expressions/array-expression.js +2 -4
- package/lib/tokenize/expressions/call-expression.js +1 -2
- package/lib/tokenize/expressions/chain/chain.js +75 -0
- package/lib/tokenize/expressions/class.js +3 -1
- package/lib/tokenize/expressions/member-expressions.js +18 -63
- package/lib/tokenize/expressions/object-expression.js +16 -3
- package/lib/tokenize/is.js +1 -1
- package/lib/tokenize/jsx/jsx-attribute.js +0 -1
- package/lib/tokenize/jsx/jsx-text.js +2 -4
- package/lib/tokenize/statements/expression-statement.js +33 -8
- package/lib/tokenize/statements/for-in-statement.js +3 -1
- package/lib/tokenize/statements/import-declaration.js +3 -1
- package/lib/tokenize/statements/switch-statement.js +3 -1
- package/lib/tokenize/statements/variable-declaration.js +3 -1
- package/package.json +1 -1
package/ChangeLog
CHANGED
|
@@ -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 (
|
|
208
|
+
if (elements.length === 2 && isIdentifierAndIdentifier(elements))
|
|
211
209
|
return false;
|
|
212
210
|
|
|
213
|
-
if (
|
|
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,
|
|
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 =
|
|
28
|
+
const isChain = likeChain(path);
|
|
29
|
+
|
|
33
30
|
maybe.indent.inc(isChain);
|
|
34
31
|
|
|
35
32
|
if (isChain) {
|
|
36
|
-
print.
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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 (
|
|
62
|
+
if (isUnaryExpression(root))
|
|
104
63
|
return false;
|
|
105
64
|
|
|
106
|
-
if (
|
|
65
|
+
if (isArrowFunctionExpression(root))
|
|
107
66
|
return false;
|
|
108
67
|
|
|
109
|
-
if (
|
|
68
|
+
if (isLogicalExpression(root))
|
|
110
69
|
return false;
|
|
111
70
|
|
|
112
|
-
const
|
|
113
|
-
const
|
|
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 (
|
|
74
|
+
if (calls.length === 2 && !firstCall.name)
|
|
120
75
|
return false;
|
|
121
76
|
|
|
122
|
-
return
|
|
77
|
+
return calls.length > 1;
|
|
123
78
|
}
|
|
@@ -7,7 +7,8 @@ const {
|
|
|
7
7
|
noTrailingComment,
|
|
8
8
|
isNewlineBetweenSiblings,
|
|
9
9
|
noLeadingComment,
|
|
10
|
-
|
|
10
|
+
hasLeadingComment,
|
|
11
|
+
exists,
|
|
11
12
|
} = require('../is');
|
|
12
13
|
|
|
13
14
|
const {isFunction} = require('@babel/types');
|
|
@@ -52,8 +53,11 @@ module.exports.ObjectExpression = (path, {print, maybe, indent}) => {
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
print(property);
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
|
|
57
|
+
if (!hasNextLeadingComment(property)) {
|
|
58
|
+
maybe.print.newline(manyLines && noTrailingComment(property));
|
|
59
|
+
maybe.print.linebreak(isNewlineBetweenSiblings(property));
|
|
60
|
+
}
|
|
57
61
|
}
|
|
58
62
|
|
|
59
63
|
indent.dec();
|
|
@@ -63,6 +67,15 @@ module.exports.ObjectExpression = (path, {print, maybe, indent}) => {
|
|
|
63
67
|
maybe.print(parens, ')');
|
|
64
68
|
};
|
|
65
69
|
|
|
70
|
+
const hasNextLeadingComment = (path) => {
|
|
71
|
+
const next = path.getNextSibling();
|
|
72
|
+
|
|
73
|
+
if (!exists(next))
|
|
74
|
+
return false;
|
|
75
|
+
|
|
76
|
+
return hasLeadingComment(next);
|
|
77
|
+
};
|
|
78
|
+
|
|
66
79
|
function shouldAddNewline(path) {
|
|
67
80
|
if (!path.parentPath.isLogicalExpression())
|
|
68
81
|
return false;
|
package/lib/tokenize/is.js
CHANGED
|
@@ -85,7 +85,7 @@ module.exports.satisfy = (conditions) => (path) => {
|
|
|
85
85
|
};
|
|
86
86
|
|
|
87
87
|
module.exports.hasTrailingComment = (path) => path.node?.trailingComments?.length;
|
|
88
|
+
module.exports.hasLeadingComment = (path) => path.node?.leadingComments?.length;
|
|
88
89
|
|
|
89
90
|
module.exports.noTrailingComment = (path) => !path.node.trailingComments?.length;
|
|
90
|
-
module.exports.noComment = (path) => !path.node.comments?.length;
|
|
91
91
|
module.exports.noLeadingComment = (path) => !path.node.leadingComments?.length;
|
|
@@ -9,16 +9,14 @@ module.exports.JSXText = (path, {write, indent}) => {
|
|
|
9
9
|
|
|
10
10
|
if (isSpacesOnly && hasNext) {
|
|
11
11
|
indent.inc();
|
|
12
|
-
write.
|
|
13
|
-
write.indent();
|
|
12
|
+
write.breakline();
|
|
14
13
|
indent.dec();
|
|
15
14
|
|
|
16
15
|
return;
|
|
17
16
|
}
|
|
18
17
|
|
|
19
18
|
if (isSpacesOnly) {
|
|
20
|
-
write.
|
|
21
|
-
write.indent();
|
|
19
|
+
write.breakline();
|
|
22
20
|
|
|
23
21
|
return;
|
|
24
22
|
}
|
|
@@ -9,12 +9,30 @@ const {
|
|
|
9
9
|
satisfy,
|
|
10
10
|
noTrailingComment,
|
|
11
11
|
hasTrailingComment,
|
|
12
|
+
exists,
|
|
12
13
|
} = require('../is');
|
|
13
14
|
|
|
15
|
+
const satisfyAfter = satisfy([
|
|
16
|
+
isParentBlockOrNotLastOrParentLast,
|
|
17
|
+
isParentBlock,
|
|
18
|
+
isNext,
|
|
19
|
+
isNextUp,
|
|
20
|
+
]);
|
|
21
|
+
|
|
14
22
|
const isNextLiteral = (path) => {
|
|
15
23
|
const next = path.getNextSibling();
|
|
24
|
+
|
|
25
|
+
if (!exists(next))
|
|
26
|
+
return false;
|
|
27
|
+
|
|
16
28
|
const expression = next.get('expression');
|
|
17
29
|
|
|
30
|
+
if (expression.isTemplateLiteral())
|
|
31
|
+
return true;
|
|
32
|
+
|
|
33
|
+
if (expression.isArrayExpression())
|
|
34
|
+
return true;
|
|
35
|
+
|
|
18
36
|
return expression.isLiteral();
|
|
19
37
|
};
|
|
20
38
|
|
|
@@ -36,15 +54,22 @@ module.exports.ExpressionStatement = {
|
|
|
36
54
|
store(true);
|
|
37
55
|
}
|
|
38
56
|
},
|
|
39
|
-
|
|
40
|
-
isParentBlockOrNotLastOrParentLast,
|
|
41
|
-
isParentBlock,
|
|
42
|
-
isNext,
|
|
43
|
-
isNextUp,
|
|
44
|
-
],
|
|
45
|
-
after(path, {print, maybe, store}) {
|
|
57
|
+
afterIf: (path) => {
|
|
46
58
|
if (hasTrailingComment(path) && isNextLiteral(path))
|
|
47
|
-
return;
|
|
59
|
+
return false;
|
|
60
|
+
|
|
61
|
+
if (satisfyAfter(path))
|
|
62
|
+
return true;
|
|
63
|
+
|
|
64
|
+
if (hasTrailingComment(path) && isLast(path))
|
|
65
|
+
return true;
|
|
66
|
+
|
|
67
|
+
return false;
|
|
68
|
+
},
|
|
69
|
+
after(path, {print, maybe, store}) {
|
|
70
|
+
if (hasTrailingComment(path) && isLast(path)) {
|
|
71
|
+
print.breakline();
|
|
72
|
+
}
|
|
48
73
|
|
|
49
74
|
print.newline();
|
|
50
75
|
maybe.markAfter(store(), path);
|
|
@@ -20,7 +20,9 @@ module.exports.SwitchStatement = {
|
|
|
20
20
|
print(switchCase.get('test'));
|
|
21
21
|
print(':');
|
|
22
22
|
|
|
23
|
-
const isBlock = switchCase
|
|
23
|
+
const isBlock = switchCase
|
|
24
|
+
.get('consequent.0')
|
|
25
|
+
.isBlockStatement();
|
|
24
26
|
|
|
25
27
|
maybe.indent.inc(!isBlock);
|
|
26
28
|
maybe.print.newline(!isBlock);
|
|
@@ -125,5 +125,7 @@ const isNextAssign = (path) => {
|
|
|
125
125
|
if (parentPath.isBlockStatement() && parentPath.node.body.length < 3)
|
|
126
126
|
return false;
|
|
127
127
|
|
|
128
|
-
return nextPath
|
|
128
|
+
return nextPath
|
|
129
|
+
.get('expression')
|
|
130
|
+
.isAssignmentExpression();
|
|
129
131
|
};
|
package/package.json
CHANGED