@putout/printer 18.6.5 → 18.7.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 +13 -0
- package/lib/tokenize/statements/switch-statement/switch-statement.js +29 -13
- package/lib/tokenize/statements/variable-declaration/after-if.js +12 -0
- package/lib/tokenize/statements/variable-declaration/is.js +32 -0
- package/lib/tokenize/statements/variable-declaration/variable-declaration.js +56 -62
- package/package.json +1 -1
package/ChangeLog
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
2026.03.14, v18.7.0
|
|
2
|
+
|
|
3
|
+
feature:
|
|
4
|
+
- b18dfef @putout/printer: SwitchStatement: space: improve support
|
|
5
|
+
- e5d54cd @putout/printer: SwitchStatement: simplify
|
|
6
|
+
|
|
7
|
+
2026.03.14, v18.6.6
|
|
8
|
+
|
|
9
|
+
feature:
|
|
10
|
+
- c4f79e0 2putout/printer: VariableDeclaration: conditions
|
|
11
|
+
- 42ea012 @putout/printer: VariableDeclaration: simplify
|
|
12
|
+
- 1d079db @putout/printer: VariableDeclaration: afterIf: skipAfter
|
|
13
|
+
|
|
1
14
|
2026.03.14, v18.6.5
|
|
2
15
|
|
|
3
16
|
feature:
|
|
@@ -1,18 +1,21 @@
|
|
|
1
|
+
import {types} from '@putout/babel';
|
|
1
2
|
import {
|
|
2
3
|
isNext,
|
|
3
4
|
exists,
|
|
4
5
|
isLast,
|
|
5
6
|
} from '#is';
|
|
6
7
|
import {parseLeadingComments} from '#comments';
|
|
8
|
+
import {createTypeChecker} from '#type-checker';
|
|
7
9
|
import {maybeSpaceAfterKeyword} from '../return-statement/maybe-space-after-keyword.js';
|
|
8
10
|
|
|
11
|
+
const {isBlockStatement} = types;
|
|
12
|
+
|
|
9
13
|
export const SwitchStatement = {
|
|
10
14
|
print(path, printer, semantics) {
|
|
11
15
|
const {
|
|
12
16
|
print,
|
|
13
17
|
maybe,
|
|
14
18
|
indent,
|
|
15
|
-
write,
|
|
16
19
|
traverse,
|
|
17
20
|
} = printer;
|
|
18
21
|
|
|
@@ -20,7 +23,9 @@ export const SwitchStatement = {
|
|
|
20
23
|
print('switch');
|
|
21
24
|
print('(');
|
|
22
25
|
print('__discriminant');
|
|
23
|
-
print(')
|
|
26
|
+
print(')');
|
|
27
|
+
print.space();
|
|
28
|
+
print('{');
|
|
24
29
|
print.newline();
|
|
25
30
|
|
|
26
31
|
const cases = path.get('cases');
|
|
@@ -28,45 +33,46 @@ export const SwitchStatement = {
|
|
|
28
33
|
|
|
29
34
|
for (const [index, switchCase] of cases.entries()) {
|
|
30
35
|
const test = switchCase.get('test');
|
|
36
|
+
const isLast = index === n;
|
|
31
37
|
|
|
32
38
|
indent();
|
|
33
39
|
|
|
34
40
|
parseLeadingComments(switchCase, printer, semantics);
|
|
35
41
|
|
|
36
42
|
if (exists(test)) {
|
|
37
|
-
|
|
43
|
+
print('case');
|
|
38
44
|
maybeSpaceAfterKeyword(test, printer, semantics);
|
|
39
45
|
traverse(test);
|
|
40
46
|
} else {
|
|
41
|
-
|
|
47
|
+
print('default');
|
|
42
48
|
}
|
|
43
49
|
|
|
44
50
|
print(':');
|
|
45
51
|
|
|
52
|
+
if (isNewlineAfterColon(switchCase))
|
|
53
|
+
print.newline();
|
|
54
|
+
|
|
46
55
|
const consequents = switchCase.get('consequent');
|
|
47
|
-
const
|
|
56
|
+
const [first] = consequents;
|
|
57
|
+
const isBlock = isBlockStatement(first);
|
|
48
58
|
|
|
49
59
|
maybe.indent.inc(!isBlock);
|
|
50
|
-
maybe.print.newline(!isBlock && consequents.length);
|
|
51
60
|
|
|
52
61
|
for (const consequent of consequents) {
|
|
53
|
-
if (
|
|
54
|
-
print(
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
62
|
+
if (isBlockStatement(consequent))
|
|
63
|
+
print.space();
|
|
57
64
|
|
|
58
|
-
print.space();
|
|
59
65
|
print(consequent);
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
maybe.indent.dec(!isBlock);
|
|
63
|
-
maybe.
|
|
69
|
+
maybe.print.linebreak(!isLast);
|
|
64
70
|
}
|
|
65
71
|
|
|
66
72
|
print.indent();
|
|
67
73
|
print('}');
|
|
68
74
|
|
|
69
|
-
if (
|
|
75
|
+
if (isNewlineAfterClosingCurlyBrace(path))
|
|
70
76
|
print.newline();
|
|
71
77
|
},
|
|
72
78
|
afterSatisfy: () => [
|
|
@@ -77,3 +83,13 @@ export const SwitchStatement = {
|
|
|
77
83
|
print.newline();
|
|
78
84
|
},
|
|
79
85
|
};
|
|
86
|
+
|
|
87
|
+
const isNewlineAfterClosingCurlyBrace = createTypeChecker([
|
|
88
|
+
['-', isNext],
|
|
89
|
+
['+: -> !', isLast],
|
|
90
|
+
]);
|
|
91
|
+
|
|
92
|
+
const isNewlineAfterColon = createTypeChecker([
|
|
93
|
+
['-: node.consequent.length -> !', Boolean],
|
|
94
|
+
['+: node.consequent.0 -> !BlockStatement'],
|
|
95
|
+
]);
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
isNext,
|
|
11
11
|
callWithPrev,
|
|
12
12
|
} from '#is';
|
|
13
|
+
import {isNewlineAfterSemicolon} from './is.js';
|
|
13
14
|
|
|
14
15
|
const {
|
|
15
16
|
isIfStatement,
|
|
@@ -67,7 +68,13 @@ const isNextAssign = createTypeChecker([
|
|
|
67
68
|
['+', callWithNext(callWithExpression(isAssignmentExpression))],
|
|
68
69
|
]);
|
|
69
70
|
|
|
71
|
+
const skipAfter = createTypeChecker([
|
|
72
|
+
['-: parentPath -> !', isLast],
|
|
73
|
+
['+: -> !', isInsideBlock],
|
|
74
|
+
]);
|
|
75
|
+
|
|
70
76
|
export const afterIf = createTypeChecker([
|
|
77
|
+
['-', skipAfter],
|
|
71
78
|
['+', callWithNext(isIfStatement)],
|
|
72
79
|
['+', callWithNext(isFunctionDeclaration)],
|
|
73
80
|
['+', noNextParentBlock],
|
|
@@ -79,3 +86,8 @@ export const afterIf = createTypeChecker([
|
|
|
79
86
|
['+: parentPath -> ExportNamedDeclaration'],
|
|
80
87
|
['+: parentPath -> TSModuleBlock'],
|
|
81
88
|
]);
|
|
89
|
+
|
|
90
|
+
export const isIndentAfterNewline = createTypeChecker([
|
|
91
|
+
['-: -> !', isNewlineAfterSemicolon],
|
|
92
|
+
['+', afterIf],
|
|
93
|
+
]);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {createTypeChecker} from '#type-checker';
|
|
2
|
+
import {
|
|
3
|
+
callWithParent,
|
|
4
|
+
isNewlineBetweenSiblings,
|
|
5
|
+
isNext,
|
|
6
|
+
noTrailingComment,
|
|
7
|
+
} from '#is';
|
|
8
|
+
|
|
9
|
+
export const isInsideParentLike = callWithParent(createTypeChecker([
|
|
10
|
+
'Program',
|
|
11
|
+
'BlockStatement',
|
|
12
|
+
'ExportNamedDeclaration',
|
|
13
|
+
'LabeledStatement',
|
|
14
|
+
]));
|
|
15
|
+
|
|
16
|
+
export const isNewlineAfterSemicolon = createTypeChecker([
|
|
17
|
+
['+: parentPath -> SwitchCase'],
|
|
18
|
+
['-: -> !', isInsideParentLike],
|
|
19
|
+
['-: -> !', isNext],
|
|
20
|
+
['+', noTrailingComment],
|
|
21
|
+
['+', isNewlineBetweenSiblings],
|
|
22
|
+
]);
|
|
23
|
+
|
|
24
|
+
export const isNeedBreaklineAfterComma = (path, {maxVariablesInOneLine}) => {
|
|
25
|
+
const {length} = path.node.declarations;
|
|
26
|
+
return length > maxVariablesInOneLine;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const isNeedSpaceAfterComma = (path, {maxVariablesInOneLine}) => {
|
|
30
|
+
const {length} = path.node.declarations;
|
|
31
|
+
return length <= maxVariablesInOneLine;
|
|
32
|
+
};
|
|
@@ -2,25 +2,32 @@ import {createTypeChecker} from '#type-checker';
|
|
|
2
2
|
import {isConcatenation} from '#is-concatenation';
|
|
3
3
|
import {maybeDeclare} from '#maybe-declare';
|
|
4
4
|
import {parseLeadingComments} from '#comments';
|
|
5
|
+
import {markAfter} from '#mark';
|
|
5
6
|
import {
|
|
6
|
-
isNext,
|
|
7
|
-
isNewlineBetweenSiblings,
|
|
8
7
|
exists,
|
|
9
|
-
noTrailingComment,
|
|
10
8
|
isInsideIf,
|
|
11
9
|
isInsideBlock,
|
|
12
10
|
isInsideTSModuleBlock,
|
|
13
11
|
isInsideProgram,
|
|
14
12
|
isInsideSwitchCase,
|
|
15
13
|
isInsideBody,
|
|
16
|
-
|
|
17
|
-
isLast,
|
|
14
|
+
hasLeadingComment,
|
|
18
15
|
} from '#is';
|
|
19
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
afterIf,
|
|
18
|
+
isIndentAfterNewline,
|
|
19
|
+
} from './after-if.js';
|
|
20
20
|
import {maybeSpaceAfterKeyword} from './maybe-space-after-keyword.js';
|
|
21
21
|
import {beforeIf} from './before-if.js';
|
|
22
|
+
import {
|
|
23
|
+
isInsideParentLike,
|
|
24
|
+
isNeedBreaklineAfterComma,
|
|
25
|
+
isNeedSpaceAfterComma,
|
|
26
|
+
isNewlineAfterSemicolon,
|
|
27
|
+
} from './is.js';
|
|
22
28
|
|
|
23
29
|
const isParentTSModuleBlock = (path) => path.parentPath.isTSModuleBlock();
|
|
30
|
+
|
|
24
31
|
const isInsideBlockLike = createTypeChecker([
|
|
25
32
|
isInsideProgram,
|
|
26
33
|
isInsideBlock,
|
|
@@ -29,29 +36,12 @@ const isInsideBlockLike = createTypeChecker([
|
|
|
29
36
|
isInsideBody,
|
|
30
37
|
]);
|
|
31
38
|
|
|
32
|
-
const isParentSwitchCase = (path) => path.parentPath.isSwitchCase();
|
|
33
|
-
|
|
34
|
-
const isInsideParentLike = callWithParent(createTypeChecker([
|
|
35
|
-
'Program',
|
|
36
|
-
'BlockStatement',
|
|
37
|
-
'ExportNamedDeclaration',
|
|
38
|
-
'LabeledStatement',
|
|
39
|
-
]));
|
|
40
|
-
|
|
41
39
|
const isNeedSemicolon = createTypeChecker([
|
|
42
|
-
isInsideParentLike,
|
|
43
|
-
|
|
44
|
-
isParentTSModuleBlock,
|
|
45
|
-
isInsideIf,
|
|
46
|
-
isInsideBody,
|
|
47
|
-
]);
|
|
48
|
-
|
|
49
|
-
const isNeedNewline = createTypeChecker([
|
|
50
|
-
['+', isParentSwitchCase],
|
|
51
|
-
['-: -> !', isInsideParentLike],
|
|
52
|
-
['-: -> !', isNext],
|
|
53
|
-
['+', noTrailingComment],
|
|
54
|
-
['+', isNewlineBetweenSiblings],
|
|
40
|
+
['+', isInsideParentLike],
|
|
41
|
+
['+: parentPath -> SwitchCase'],
|
|
42
|
+
['+', isParentTSModuleBlock],
|
|
43
|
+
['+', isInsideIf],
|
|
44
|
+
['+', isInsideBody],
|
|
55
45
|
]);
|
|
56
46
|
|
|
57
47
|
export const VariableDeclaration = {
|
|
@@ -59,12 +49,21 @@ export const VariableDeclaration = {
|
|
|
59
49
|
before(path, {print}) {
|
|
60
50
|
print.breakline();
|
|
61
51
|
},
|
|
62
|
-
print: maybeDeclare((path,
|
|
52
|
+
print: maybeDeclare((path, printer, semantics) => {
|
|
53
|
+
const {kind} = path.node;
|
|
54
|
+
const {
|
|
55
|
+
maybe,
|
|
56
|
+
write,
|
|
57
|
+
traverse,
|
|
58
|
+
indent,
|
|
59
|
+
} = printer;
|
|
60
|
+
|
|
63
61
|
const {maxVariablesInOneLine} = semantics;
|
|
64
62
|
|
|
65
|
-
|
|
63
|
+
if (isInsideBlockLike(path))
|
|
64
|
+
indent();
|
|
66
65
|
|
|
67
|
-
write(
|
|
66
|
+
write(kind);
|
|
68
67
|
maybeSpaceAfterKeyword(path, {
|
|
69
68
|
write,
|
|
70
69
|
});
|
|
@@ -88,47 +87,42 @@ export const VariableDeclaration = {
|
|
|
88
87
|
traverse(init);
|
|
89
88
|
}
|
|
90
89
|
|
|
91
|
-
if (
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
parseLeadingComments(next, {print, maybe, indent}, semantics);
|
|
90
|
+
if (isLast)
|
|
91
|
+
continue;
|
|
92
|
+
|
|
93
|
+
const next = declarations[index + 1];
|
|
94
|
+
|
|
95
|
+
write(',');
|
|
96
|
+
|
|
97
|
+
if (hasLeadingComment(next)) {
|
|
98
|
+
parseLeadingComments(next, printer, semantics);
|
|
99
|
+
continue;
|
|
103
100
|
}
|
|
101
|
+
|
|
102
|
+
if (isNeedBreaklineAfterComma(path, {maxVariablesInOneLine})) {
|
|
103
|
+
write.breakline();
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (isNeedSpaceAfterComma(path, {maxVariablesInOneLine}))
|
|
108
|
+
write.space();
|
|
104
109
|
}
|
|
105
110
|
|
|
106
111
|
maybe.indent.dec(n);
|
|
107
|
-
maybe.write(isNeedSemicolon(path), ';');
|
|
108
112
|
|
|
109
|
-
|
|
113
|
+
if (isNeedSemicolon(path))
|
|
114
|
+
write(';');
|
|
110
115
|
|
|
111
|
-
if (
|
|
116
|
+
if (isNewlineAfterSemicolon(path))
|
|
112
117
|
write.newline();
|
|
113
|
-
wasNewline = true;
|
|
114
|
-
}
|
|
115
118
|
|
|
116
|
-
|
|
119
|
+
if (isIndentAfterNewline(path)) {
|
|
120
|
+
indent();
|
|
121
|
+
markAfter(path);
|
|
122
|
+
}
|
|
117
123
|
}),
|
|
118
124
|
afterIf,
|
|
119
|
-
after(path, {
|
|
120
|
-
const wasNewline = store();
|
|
121
|
-
|
|
122
|
-
if (skipAfter(path))
|
|
123
|
-
return;
|
|
124
|
-
|
|
125
|
-
maybe.indent(wasNewline);
|
|
125
|
+
after(path, {print}) {
|
|
126
126
|
print.newline();
|
|
127
|
-
maybe.markAfter(wasNewline, path);
|
|
128
127
|
},
|
|
129
128
|
};
|
|
130
|
-
|
|
131
|
-
const skipAfter = createTypeChecker([
|
|
132
|
-
['-: parentPath -> !', isLast],
|
|
133
|
-
['+: -> !', isInsideBlock],
|
|
134
|
-
]);
|
package/package.json
CHANGED