@putout/printer 18.26.0 → 18.28.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
+ 2026.07.03, v18.28.0
2
+
3
+ feature:
4
+ - 64e0fc9a @putout/printer: ExpressionStatement: comments
5
+
6
+ 2026.07.02, v18.27.0
7
+
8
+ feature:
9
+ - 45cb944d @putout/printer: type-checker: types
10
+
1
11
  2026.06.27, v18.26.0
2
12
 
3
13
  feature:
@@ -1,6 +1,18 @@
1
1
  const createPrintCommentLine = (fn, value) => () => fn(`//${value}`);
2
2
  const createPrintCommentBlock = (fn, value) => () => fn(`/*${value}*/\n`);
3
3
 
4
+ const isCommentBlock = (node) => node.type === 'CommentBlock';
5
+ const isCommentLine = (node) => node.type === 'CommentLine';
6
+
7
+ function isSameLine(path, loc) {
8
+ const {node} = path;
9
+
10
+ if (!node.loc)
11
+ return false;
12
+
13
+ return node.loc.start.line === loc.start.line;
14
+ }
15
+
4
16
  export const hasTrailingCommentsPrinter = (currentTraverse) => {
5
17
  const {
6
18
  printTrailingCommentBlock,
@@ -38,8 +50,10 @@ export const printLeadingComments = (path, printer, semantics, {currentTraverse}
38
50
 
39
51
  const n = leadingComments.length - 1;
40
52
 
41
- for (const [index, {type, value}] of leadingComments.entries()) {
42
- if (type === 'CommentLine') {
53
+ for (const [index, comment] of leadingComments.entries()) {
54
+ const {value} = comment;
55
+
56
+ if (isCommentLine(comment)) {
43
57
  printLeadingCommentLine?.(path, printer, semantics, {
44
58
  index,
45
59
  printComment: createPrintCommentLine(print, value),
@@ -48,7 +62,7 @@ export const printLeadingComments = (path, printer, semantics, {currentTraverse}
48
62
  continue;
49
63
  }
50
64
 
51
- if (type === 'CommentBlock')
65
+ if (isCommentBlock(comment))
52
66
  printLeadingCommentBlock?.(path, printer, semantics, {
53
67
  index,
54
68
  printComment: createPrintCommentBlock(print, value),
@@ -69,20 +83,24 @@ export const printTrailingComments = (path, printer, semantics, {currentTraverse
69
83
 
70
84
  const n = trailingComments.length - 1;
71
85
 
72
- for (const [index, {type, value}] of trailingComments.entries()) {
73
- if (type === 'CommentLine') {
86
+ for (const [index, comment] of trailingComments.entries()) {
87
+ const {loc, value} = comment;
88
+
89
+ if (isCommentLine(comment)) {
74
90
  printTrailingCommentLine?.(path, printer, semantics, {
75
91
  index,
76
92
  printComment: createPrintCommentLine(print, value),
77
93
  isLast: index === n,
94
+ isSameLine: isSameLine(path, loc),
78
95
  });
79
96
  continue;
80
97
  }
81
98
 
82
- if (type === 'CommentBlock')
83
- printTrailingCommentBlock?.(path, printer, semantics, {
84
- index,
85
- printComment: createPrintCommentBlock(print, value),
86
- });
99
+ isCommentBlock(comment);
100
+
101
+ printTrailingCommentBlock?.(path, printer, semantics, {
102
+ index,
103
+ printComment: createPrintCommentBlock(print, value),
104
+ });
87
105
  }
88
106
  };
@@ -13,7 +13,6 @@ import {
13
13
  const {
14
14
  isDecorator,
15
15
  isMemberExpression,
16
- isExpressionStatement,
17
16
  isCallExpression,
18
17
  } = types;
19
18
 
@@ -77,9 +76,6 @@ function isCommentOnNextLine(path) {
77
76
  if (next.node && line < next.node.loc?.start.line)
78
77
  return false;
79
78
 
80
- if (!loc)
81
- return true;
82
-
83
79
  const startLine = loc.start.line;
84
80
  const endLine = loc.end.line;
85
81
  const isNextLine = line === startLine + 1 && line === endLine + 1;
@@ -154,15 +150,7 @@ export const parseTrailingComments = (path, printer, semantics, {currentTraverse
154
150
  };
155
151
 
156
152
  function isPrevCall(path) {
157
- const prev = path.getPrevSibling();
158
-
159
- if (isExpressionStatement(prev))
160
- return false;
161
-
162
153
  const {expression} = path.node;
163
154
 
164
- if (!isCallExpression(expression))
165
- return false;
166
-
167
- return !isCallExpression(expression.arguments[0]);
155
+ return isCallExpression(expression);
168
156
  }
@@ -1,5 +1,11 @@
1
1
  import {types} from '@putout/babel';
2
- import {hasTrailingComment} from '#is';
2
+ import {createTypeChecker} from '#type-checker';
3
+ import {
4
+ isNext,
5
+ hasTrailingComment,
6
+ isInsideBlock,
7
+ callWithNext,
8
+ } from '#is';
3
9
 
4
10
  const {
5
11
  isBlockStatement,
@@ -25,6 +31,33 @@ export const printLeadingCommentLine = (path, printer, semantics, {index, isLast
25
31
  print.indent();
26
32
  };
27
33
 
34
+ export const printTrailingCommentLine = (path, printer, semantics, {isSameLine, printComment}) => {
35
+ const {print} = printer;
36
+
37
+ if (isSameLine)
38
+ print.space();
39
+ else if (!isNext(path) || isNextNotSimple(path))
40
+ print.breakline();
41
+ else
42
+ print.indent();
43
+
44
+ printComment();
45
+
46
+ if (isNext(path) || isInsideBlock(path))
47
+ print.newline();
48
+ };
49
+
50
+ const isSimple = createTypeChecker([
51
+ '+: node.expression -> StringLiteral',
52
+ '+: node.expression -> TemplateLiteral',
53
+ '+: node.expression -> ArrayExpression',
54
+ '+: node.expression -> BooleanLiteral',
55
+ ]);
56
+
57
+ const isNextNotSimple = createTypeChecker([
58
+ ['+: -> !', callWithNext(isSimple)],
59
+ ]);
60
+
28
61
  export const printLeadingCommentBlock = (path, printer, semantics, {printComment}) => {
29
62
  const {indent} = printer;
30
63
  const prev = path.getPrevSibling();
@@ -37,3 +70,12 @@ export const printLeadingCommentBlock = (path, printer, semantics, {printComment
37
70
 
38
71
  printComment();
39
72
  };
73
+
74
+ export const printTrailingCommentBlock = (path, printer, semantics, {printComment}) => {
75
+ const {print} = printer;
76
+
77
+ if (isNext(path))
78
+ print.breakline();
79
+
80
+ printComment();
81
+ };
@@ -7,18 +7,20 @@ import {
7
7
  isInsideReturn,
8
8
  callWithNext,
9
9
  hasLeadingComment,
10
+ hasTrailingComment,
10
11
  } from '#is';
12
+ import {afterIf} from './after-if.js';
13
+ import {beforeIf} from './before-if.js';
11
14
  import {
12
15
  printLeadingCommentLine,
13
16
  printLeadingCommentBlock,
17
+ printTrailingCommentLine,
18
+ printTrailingCommentBlock,
14
19
  } from './comments.js';
15
- import {afterIf} from './after-if.js';
16
- import {beforeIf} from './before-if.js';
17
20
 
18
21
  const {isIfStatement} = types;
19
22
 
20
23
  const isCallInsideExpression = createTypeChecker([
21
- '-: -> !ExpressionStatement',
22
24
  '+: node.expression -> CallExpression',
23
25
  ]);
24
26
 
@@ -27,12 +29,6 @@ const isNextToAssignmentCall = createTypeChecker([
27
29
  ['+', callWithNext(isCallInsideExpression)],
28
30
  ]);
29
31
 
30
- const isNextStatementWithBlockComment = createTypeChecker([
31
- '-: node.expression -> !CallExpression',
32
- '-: node.expression.arguments.0 -> !CallExpression',
33
- '+: node.trailingComments.0 -> CommentBlock',
34
- ]);
35
-
36
32
  const isBreakline = createTypeChecker([
37
33
  ['+', isNewlineBetweenSiblings],
38
34
  ['+', callWithNext(isIfStatement)],
@@ -40,8 +36,8 @@ const isBreakline = createTypeChecker([
40
36
 
41
37
  const isIndent = createTypeChecker([
42
38
  noTrailingComment,
39
+ callWithNext(isIfStatement),
43
40
  isNextToAssignmentCall,
44
- isNextStatementWithBlockComment,
45
41
  ]);
46
42
 
47
43
  export const isIndentAfter = createTypeChecker([
@@ -52,6 +48,8 @@ export const isIndentAfter = createTypeChecker([
52
48
  export const ExpressionStatement = {
53
49
  printLeadingCommentLine,
54
50
  printLeadingCommentBlock,
51
+ printTrailingCommentLine,
52
+ printTrailingCommentBlock,
55
53
  beforeIf,
56
54
  before(path, {indent}) {
57
55
  indent();
@@ -73,18 +71,13 @@ export const ExpressionStatement = {
73
71
  after(path, {print, maybe, store}) {
74
72
  maybe.indent(isIndentAfter(path));
75
73
 
76
- if (!isNextSimpleWithLeadingComments(path))
74
+ if (isNewlineAfter(path))
77
75
  print.newline();
78
76
 
79
77
  maybe.markAfter(store(), path);
80
78
  },
81
79
  };
82
80
 
83
- export const isNextSimpleWithLeadingComments = callWithNext(createTypeChecker([
84
- ['-: -> !', hasLeadingComment],
85
- ['-: -> !ExpressionStatement'],
86
- ['+: node.expression -> TemplateLiteral'],
87
- ['+: node.expression -> ArrayExpression'],
88
- ['+: node.expression -> BooleanLiteral'],
89
- ['+: node.expression -> StringLiteral'],
90
- ]));
81
+ export const isNewlineAfter = createTypeChecker([
82
+ ['+: -> !', hasTrailingComment],
83
+ ]);
@@ -0,0 +1,19 @@
1
+ type TypeChecker = (path: unknown, options?: Record<string, unknown>) => boolean;
2
+ type CoverageEntry = {
3
+ covered: Set<number>;
4
+ typeNames: unknown[];
5
+ };
6
+ type InstrumentOverride = {
7
+ env?: {
8
+ TYPE_CHECK?: string;
9
+ [key: string]: unknown;
10
+ };
11
+ coverage?: Map<string, CoverageEntry>;
12
+ instrumentName?: string;
13
+ [key: string]: unknown;
14
+ };
15
+
16
+ export function instrument(typeNames: unknown[], fn: TypeChecker, overrides?: InstrumentOverride): TypeChecker;
17
+
18
+ export function getCoverage(): Map<string, CoverageEntry>;
19
+
@@ -0,0 +1,7 @@
1
+ type CoverageEntry = {
2
+ covered: Set<number>;
3
+ typeNames: unknown[];
4
+ };
5
+
6
+ export function report(coverage: Map<string, CoverageEntry>): [number, string];
7
+
@@ -0,0 +1,9 @@
1
+ type TypeChecker = (path: unknown, options?: Record<string, unknown>) => boolean;
2
+ type TypeCheckerOverride = {
3
+ instrumentCoverage?: (typeNames: unknown[], fn: TypeChecker, overrides?: Record<string, unknown>) => TypeChecker;
4
+ instrumentName?: string;
5
+ [key: string]: unknown;
6
+ };
7
+
8
+ export function createTypeChecker(typeNames: unknown[], overrides?: TypeCheckerOverride): TypeChecker;
9
+
@@ -0,0 +1,15 @@
1
+ type WhenTestsEndsOverride = {
2
+ log?: (message: string) => void;
3
+ getCoverage?: () => Map<string, {
4
+ covered: Set<number>;
5
+ typeNames: unknown[];
6
+ }>;
7
+ report?: (coverage: Map<string, {
8
+ covered: Set<number>;
9
+ typeNames: unknown[];
10
+ }>) => [number, string];
11
+ [key: string]: unknown;
12
+ };
13
+
14
+ export function whenTestsEnds(overrides?: WhenTestsEndsOverride): number;
15
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@putout/printer",
3
- "version": "18.26.0",
3
+ "version": "18.28.0",
4
4
  "type": "module",
5
5
  "author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
6
6
  "description": "Simplest possible opinionated Babel AST printer for 🐊Putout",
package/tsconfig.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "moduleResolution": "nodenext",
4
- "module": "NodeNext",
5
- "target": "es2015",
6
- "skipLibCheck": true
7
- },
8
- "include": ["lib/printer.d.ts", "test/*.ts"]
9
- }