rawsql-ts 0.24.2 → 0.24.4

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.
Files changed (83) hide show
  1. package/README.md +10 -1
  2. package/dist/esm/index.min.js +9 -9
  3. package/dist/esm/index.min.js.map +2 -2
  4. package/dist/esm/models/ValueComponent.d.ts +2 -1
  5. package/dist/esm/models/ValueComponent.js +2 -1
  6. package/dist/esm/models/ValueComponent.js.map +1 -1
  7. package/dist/esm/parsers/CommandExpressionParser.d.ts +2 -0
  8. package/dist/esm/parsers/CommandExpressionParser.js +49 -4
  9. package/dist/esm/parsers/CommandExpressionParser.js.map +1 -1
  10. package/dist/esm/parsers/HavingParser.js +6 -0
  11. package/dist/esm/parsers/HavingParser.js.map +1 -1
  12. package/dist/esm/parsers/JoinOnClauseParser.js +6 -0
  13. package/dist/esm/parsers/JoinOnClauseParser.js.map +1 -1
  14. package/dist/esm/parsers/LimitClauseParser.js +6 -0
  15. package/dist/esm/parsers/LimitClauseParser.js.map +1 -1
  16. package/dist/esm/parsers/OffsetClauseParser.js +6 -0
  17. package/dist/esm/parsers/OffsetClauseParser.js.map +1 -1
  18. package/dist/esm/parsers/OrderByClauseParser.d.ts +2 -0
  19. package/dist/esm/parsers/OrderByClauseParser.js +42 -29
  20. package/dist/esm/parsers/OrderByClauseParser.js.map +1 -1
  21. package/dist/esm/parsers/ParameterDecorator.d.ts +2 -2
  22. package/dist/esm/parsers/ParameterDecorator.js +1 -1
  23. package/dist/esm/parsers/ParameterDecorator.js.map +1 -1
  24. package/dist/esm/parsers/ParameterExpressionParser.js +2 -1
  25. package/dist/esm/parsers/ParameterExpressionParser.js.map +1 -1
  26. package/dist/esm/parsers/SqlPrintTokenParser.d.ts +18 -4
  27. package/dist/esm/parsers/SqlPrintTokenParser.js +135 -18
  28. package/dist/esm/parsers/SqlPrintTokenParser.js.map +1 -1
  29. package/dist/esm/parsers/ValueParser.js +5 -3
  30. package/dist/esm/parsers/ValueParser.js.map +1 -1
  31. package/dist/esm/transformers/FormatOptionResolver.js +1 -0
  32. package/dist/esm/transformers/FormatOptionResolver.js.map +1 -1
  33. package/dist/esm/transformers/LinePrinter.d.ts +1 -1
  34. package/dist/esm/transformers/OnelineFormattingHelper.d.ts +1 -0
  35. package/dist/esm/transformers/OnelineFormattingHelper.js.map +1 -1
  36. package/dist/esm/transformers/SqlFormatter.d.ts +9 -5
  37. package/dist/esm/transformers/SqlFormatter.js +4 -4
  38. package/dist/esm/transformers/SqlFormatter.js.map +1 -1
  39. package/dist/esm/transformers/SqlPrinter.d.ts +26 -2
  40. package/dist/esm/transformers/SqlPrinter.js +325 -26
  41. package/dist/esm/transformers/SqlPrinter.js.map +1 -1
  42. package/dist/index.min.js +9 -9
  43. package/dist/index.min.js.map +2 -2
  44. package/dist/models/ValueComponent.js +2 -1
  45. package/dist/models/ValueComponent.js.map +1 -1
  46. package/dist/parsers/CommandExpressionParser.js +49 -4
  47. package/dist/parsers/CommandExpressionParser.js.map +1 -1
  48. package/dist/parsers/HavingParser.js +6 -0
  49. package/dist/parsers/HavingParser.js.map +1 -1
  50. package/dist/parsers/JoinOnClauseParser.js +6 -0
  51. package/dist/parsers/JoinOnClauseParser.js.map +1 -1
  52. package/dist/parsers/LimitClauseParser.js +6 -0
  53. package/dist/parsers/LimitClauseParser.js.map +1 -1
  54. package/dist/parsers/OffsetClauseParser.js +6 -0
  55. package/dist/parsers/OffsetClauseParser.js.map +1 -1
  56. package/dist/parsers/OrderByClauseParser.js +42 -29
  57. package/dist/parsers/OrderByClauseParser.js.map +1 -1
  58. package/dist/parsers/ParameterDecorator.js +1 -1
  59. package/dist/parsers/ParameterDecorator.js.map +1 -1
  60. package/dist/parsers/ParameterExpressionParser.js +2 -1
  61. package/dist/parsers/ParameterExpressionParser.js.map +1 -1
  62. package/dist/parsers/SqlPrintTokenParser.js +136 -18
  63. package/dist/parsers/SqlPrintTokenParser.js.map +1 -1
  64. package/dist/parsers/ValueParser.js +5 -3
  65. package/dist/parsers/ValueParser.js.map +1 -1
  66. package/dist/src/models/ValueComponent.d.ts +2 -1
  67. package/dist/src/parsers/CommandExpressionParser.d.ts +2 -0
  68. package/dist/src/parsers/OrderByClauseParser.d.ts +2 -0
  69. package/dist/src/parsers/ParameterDecorator.d.ts +2 -2
  70. package/dist/src/parsers/SqlPrintTokenParser.d.ts +18 -4
  71. package/dist/src/transformers/LinePrinter.d.ts +1 -1
  72. package/dist/src/transformers/OnelineFormattingHelper.d.ts +1 -0
  73. package/dist/src/transformers/SqlFormatter.d.ts +9 -5
  74. package/dist/src/transformers/SqlPrinter.d.ts +26 -2
  75. package/dist/transformers/FormatOptionResolver.js +1 -0
  76. package/dist/transformers/FormatOptionResolver.js.map +1 -1
  77. package/dist/transformers/OnelineFormattingHelper.js.map +1 -1
  78. package/dist/transformers/SqlFormatter.js +5 -3
  79. package/dist/transformers/SqlFormatter.js.map +1 -1
  80. package/dist/transformers/SqlPrinter.js +325 -26
  81. package/dist/transformers/SqlPrinter.js.map +1 -1
  82. package/dist/tsconfig.browser.tsbuildinfo +1 -1
  83. package/package.json +2 -2
@@ -33,7 +33,7 @@ class SqlPrinter {
33
33
  * @param options Optional style settings for pretty printing
34
34
  */
35
35
  constructor(options) {
36
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
36
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
37
37
  /** Track whether we are currently inside a WITH clause for full-oneline formatting */
38
38
  this.insideWithClause = false;
39
39
  /** Tracks nesting depth while formatting MERGE WHEN predicate segments */
@@ -46,6 +46,8 @@ class SqlPrinter {
46
46
  this.pendingLineCommentBreak = null;
47
47
  /** Accumulates lines when reconstructing multi-line block comments inside CommentBlocks */
48
48
  this.smartCommentBlockBuilder = null;
49
+ /** Tracks function calls whose arguments must expand because rendered comments are present */
50
+ this.commentedFunctionCallDepth = 0;
49
51
  // Resolve logical options to their control character representations before applying defaults.
50
52
  const resolvedIndentChar = (0, FormatOptionResolver_1.resolveIndentCharOption)(options === null || options === void 0 ? void 0 : options.indentChar);
51
53
  const resolvedNewline = (0, FormatOptionResolver_1.resolveNewlineOption)(options === null || options === void 0 ? void 0 : options.newline);
@@ -59,26 +61,28 @@ class SqlPrinter {
59
61
  this.valuesCommaBreak = (_d = options === null || options === void 0 ? void 0 : options.valuesCommaBreak) !== null && _d !== void 0 ? _d : this.commaBreak;
60
62
  this.andBreak = (_e = options === null || options === void 0 ? void 0 : options.andBreak) !== null && _e !== void 0 ? _e : 'none';
61
63
  this.orBreak = (_f = options === null || options === void 0 ? void 0 : options.orBreak) !== null && _f !== void 0 ? _f : 'none';
62
- this.joinOnBreak = (_g = options === null || options === void 0 ? void 0 : options.joinOnBreak) !== null && _g !== void 0 ? _g : 'none';
63
- this.keywordCase = (_h = options === null || options === void 0 ? void 0 : options.keywordCase) !== null && _h !== void 0 ? _h : 'none';
64
+ this.joinOnBreak = this.normalizeJoinOnBreak(options === null || options === void 0 ? void 0 : options.joinOnBreak);
65
+ this.keywordCase = this.normalizeKeywordCase(options === null || options === void 0 ? void 0 : options.keywordCase);
64
66
  this.commentExportMode = this.resolveCommentExportMode(options === null || options === void 0 ? void 0 : options.exportComment);
65
- this.withClauseStyle = (_j = options === null || options === void 0 ? void 0 : options.withClauseStyle) !== null && _j !== void 0 ? _j : 'standard';
66
- this.commentStyle = (_k = options === null || options === void 0 ? void 0 : options.commentStyle) !== null && _k !== void 0 ? _k : 'block';
67
- this.parenthesesOneLine = (_l = options === null || options === void 0 ? void 0 : options.parenthesesOneLine) !== null && _l !== void 0 ? _l : false;
68
- this.betweenOneLine = (_m = options === null || options === void 0 ? void 0 : options.betweenOneLine) !== null && _m !== void 0 ? _m : false;
69
- this.valuesOneLine = (_o = options === null || options === void 0 ? void 0 : options.valuesOneLine) !== null && _o !== void 0 ? _o : false;
70
- this.joinOneLine = (_p = options === null || options === void 0 ? void 0 : options.joinOneLine) !== null && _p !== void 0 ? _p : false;
71
- this.caseOneLine = (_q = options === null || options === void 0 ? void 0 : options.caseOneLine) !== null && _q !== void 0 ? _q : false;
72
- this.subqueryOneLine = (_r = options === null || options === void 0 ? void 0 : options.subqueryOneLine) !== null && _r !== void 0 ? _r : false;
73
- this.indentNestedParentheses = (_s = options === null || options === void 0 ? void 0 : options.indentNestedParentheses) !== null && _s !== void 0 ? _s : false;
74
- this.insertColumnsOneLine = (_t = options === null || options === void 0 ? void 0 : options.insertColumnsOneLine) !== null && _t !== void 0 ? _t : false;
75
- this.whenOneLine = (_u = options === null || options === void 0 ? void 0 : options.whenOneLine) !== null && _u !== void 0 ? _u : false;
67
+ this.withClauseStyle = (_g = options === null || options === void 0 ? void 0 : options.withClauseStyle) !== null && _g !== void 0 ? _g : 'standard';
68
+ this.commentStyle = (_h = options === null || options === void 0 ? void 0 : options.commentStyle) !== null && _h !== void 0 ? _h : 'block';
69
+ this.parenthesesOneLine = (_j = options === null || options === void 0 ? void 0 : options.parenthesesOneLine) !== null && _j !== void 0 ? _j : false;
70
+ this.betweenOneLine = (_k = options === null || options === void 0 ? void 0 : options.betweenOneLine) !== null && _k !== void 0 ? _k : false;
71
+ this.valuesOneLine = (_l = options === null || options === void 0 ? void 0 : options.valuesOneLine) !== null && _l !== void 0 ? _l : false;
72
+ this.inOneLine = (_m = options === null || options === void 0 ? void 0 : options.inOneLine) !== null && _m !== void 0 ? _m : false;
73
+ this.joinOneLine = (_o = options === null || options === void 0 ? void 0 : options.joinOneLine) !== null && _o !== void 0 ? _o : false;
74
+ this.caseOneLine = (_p = options === null || options === void 0 ? void 0 : options.caseOneLine) !== null && _p !== void 0 ? _p : false;
75
+ this.subqueryOneLine = (_q = options === null || options === void 0 ? void 0 : options.subqueryOneLine) !== null && _q !== void 0 ? _q : false;
76
+ this.indentNestedParentheses = (_r = options === null || options === void 0 ? void 0 : options.indentNestedParentheses) !== null && _r !== void 0 ? _r : false;
77
+ this.insertColumnsOneLine = (_s = options === null || options === void 0 ? void 0 : options.insertColumnsOneLine) !== null && _s !== void 0 ? _s : false;
78
+ this.whenOneLine = (_t = options === null || options === void 0 ? void 0 : options.whenOneLine) !== null && _t !== void 0 ? _t : false;
76
79
  this.oneLineMaxLength = this.normalizeOneLineMaxLength(options === null || options === void 0 ? void 0 : options.oneLineMaxLength);
77
- this.joinConditionContinuationIndent = (_v = options === null || options === void 0 ? void 0 : options.joinConditionContinuationIndent) !== null && _v !== void 0 ? _v : false;
80
+ this.joinConditionContinuationIndent = (_u = options === null || options === void 0 ? void 0 : options.joinConditionContinuationIndent) !== null && _u !== void 0 ? _u : false;
78
81
  const onelineOptions = {
79
82
  parenthesesOneLine: this.parenthesesOneLine,
80
83
  betweenOneLine: this.betweenOneLine,
81
84
  valuesOneLine: this.valuesOneLine,
85
+ inOneLine: this.inOneLine,
82
86
  joinOneLine: this.joinOneLine,
83
87
  caseOneLine: this.caseOneLine,
84
88
  subqueryOneLine: this.subqueryOneLine,
@@ -88,7 +92,7 @@ class SqlPrinter {
88
92
  this.onelineHelper = new OnelineFormattingHelper_1.OnelineFormattingHelper(onelineOptions);
89
93
  this.linePrinter = new LinePrinter_1.LinePrinter(this.indentChar, this.indentSize, this.newline, this.commaBreak);
90
94
  // Initialize
91
- this.indentIncrementContainers = new Set((_w = options === null || options === void 0 ? void 0 : options.indentIncrementContainerTypes) !== null && _w !== void 0 ? _w : [
95
+ this.indentIncrementContainers = new Set((_v = options === null || options === void 0 ? void 0 : options.indentIncrementContainerTypes) !== null && _v !== void 0 ? _v : [
92
96
  SqlPrintToken_1.SqlPrintTokenContainerType.SelectClause,
93
97
  SqlPrintToken_1.SqlPrintTokenContainerType.ReturningClause,
94
98
  SqlPrintToken_1.SqlPrintTokenContainerType.FromClause,
@@ -138,6 +142,7 @@ class SqlPrinter {
138
142
  this.pendingLineCommentBreak = null;
139
143
  this.smartCommentBlockBuilder = null;
140
144
  this.expandedOneLineFallbackTokens = new WeakSet();
145
+ this.commentedFunctionCallDepth = 0;
141
146
  if (this.linePrinter.lines.length > 0 && level !== this.linePrinter.lines[0].level) {
142
147
  this.linePrinter.lines[0].level = level;
143
148
  }
@@ -180,6 +185,7 @@ class SqlPrinter {
180
185
  }
181
186
  }
182
187
  appendToken(token, level, parentContainerType, caseContextDepth = 0, indentParentActive = false, commentContext, previousSiblingWasOpenParen = false) {
188
+ var _a;
183
189
  // Track WITH clause context for full-oneline formatting
184
190
  const wasInsideWithClause = this.insideWithClause;
185
191
  if (token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.WithClause && this.withClauseStyle === 'full-oneline') {
@@ -208,12 +214,16 @@ class SqlPrinter {
208
214
  }
209
215
  }
210
216
  const hasRenderableLeadingComment = leadingCommentContexts.some(item => item.shouldRender);
217
+ const leadingCommentFollowsLogicalOperator = hasRenderableLeadingComment && this.currentLineEndsWithLogicalOperator();
211
218
  const leadingCommentIndentLevel = hasRenderableLeadingComment
212
- ? this.getLeadingCommentIndentLevel(parentContainerType, level)
219
+ ? this.getLeadingCommentIndentLevel(token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.SelectItem
220
+ ? token.containerType
221
+ : parentContainerType, level)
213
222
  : null;
214
223
  if (hasRenderableLeadingComment
215
224
  && !this.isOnelineMode()
216
- && this.shouldAddNewlineBeforeLeadingComments(parentContainerType)) {
225
+ && this.shouldAddNewlineBeforeLeadingComments(parentContainerType)
226
+ && !this.shouldKeepLeadingCommentOnCommaLine()) {
217
227
  const currentLine = this.linePrinter.getCurrentLine();
218
228
  if (currentLine.text.trim().length > 0) {
219
229
  // Align the newline before leading comments with the intended comment indentation.
@@ -226,13 +236,38 @@ class SqlPrinter {
226
236
  }
227
237
  // Keep leading comment processing aligned with its computed indentation level.
228
238
  this.appendToken(leading.token, leadingCommentIndentLevel !== null && leadingCommentIndentLevel !== void 0 ? leadingCommentIndentLevel : level, token.containerType, caseContextDepth, indentParentActive, leading.context, false);
239
+ if (token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.SelectItem &&
240
+ ((_a = this.smartCommentBlockBuilder) === null || _a === void 0 ? void 0 : _a.mode) === 'line') {
241
+ this.flushSmartCommentBlockBuilder();
242
+ }
243
+ if (containerIsTopLevel &&
244
+ !this.isOnelineMode() &&
245
+ this.pendingLineCommentBreak === null &&
246
+ this.linePrinter.getCurrentLine().text.trim() !== '') {
247
+ this.linePrinter.appendNewline(level);
248
+ }
249
+ }
250
+ if (hasRenderableLeadingComment &&
251
+ containerIsTopLevel &&
252
+ !this.isOnelineMode() &&
253
+ this.linePrinter.getCurrentLine().text.trim() !== '') {
254
+ this.linePrinter.appendNewline(level);
255
+ }
256
+ if (leadingCommentFollowsLogicalOperator &&
257
+ this.pendingLineCommentBreak === null &&
258
+ !this.isOnelineMode() &&
259
+ this.linePrinter.getCurrentLine().text.trim().endsWith('*/')) {
260
+ this.linePrinter.appendNewline(level + 1);
229
261
  }
230
262
  if (this.smartCommentBlockBuilder && token.containerType !== SqlPrintToken_1.SqlPrintTokenContainerType.CommentBlock && token.type !== SqlPrintToken_1.SqlPrintTokenType.commentNewline) {
231
263
  this.flushSmartCommentBlockBuilder();
232
264
  }
233
265
  if (this.pendingLineCommentBreak !== null) {
234
266
  if (!this.isOnelineMode()) {
235
- this.linePrinter.appendNewline(this.pendingLineCommentBreak);
267
+ const pendingBreakLevel = leadingCommentFollowsLogicalOperator
268
+ ? this.pendingLineCommentBreak + 1
269
+ : this.pendingLineCommentBreak;
270
+ this.linePrinter.appendNewline(pendingBreakLevel);
236
271
  }
237
272
  const shouldSkipToken = token.type === SqlPrintToken_1.SqlPrintTokenType.commentNewline;
238
273
  this.pendingLineCommentBreak = null;
@@ -249,7 +284,15 @@ class SqlPrinter {
249
284
  if (!this.shouldRenderComment(token, effectiveCommentContext)) {
250
285
  return;
251
286
  }
287
+ if (this.shouldKeepLeadingCommentOnCommaLine()) {
288
+ this.ensureTrailingSpace();
289
+ }
252
290
  const commentLevel = this.getCommentBaseIndentLevel(level, parentContainerType);
291
+ if (parentContainerType === SqlPrintToken_1.SqlPrintTokenContainerType.SelectItem &&
292
+ effectiveCommentContext.position === 'leading' &&
293
+ this.linePrinter.getCurrentLine().text.trim() === '') {
294
+ this.linePrinter.getCurrentLine().level = commentLevel;
295
+ }
253
296
  this.handleCommentBlockContainer(token, commentLevel, effectiveCommentContext);
254
297
  return;
255
298
  }
@@ -264,6 +307,9 @@ class SqlPrinter {
264
307
  else if (token.type === SqlPrintToken_1.SqlPrintTokenType.comma) {
265
308
  this.handleCommaToken(token, level, parentContainerType);
266
309
  }
310
+ else if (token.type === SqlPrintToken_1.SqlPrintTokenType.argumentSplitter) {
311
+ this.handleArgumentSplitterToken(token, level, parentContainerType);
312
+ }
267
313
  else if (token.type === SqlPrintToken_1.SqlPrintTokenType.parenthesis) {
268
314
  this.handleParenthesisToken(token, level, indentParentActive, parentContainerType);
269
315
  }
@@ -297,6 +343,9 @@ class SqlPrinter {
297
343
  return; // Return early to avoid processing innerTokens
298
344
  }
299
345
  }
346
+ else if (this.inOneLine && this.isInValueListExpression(token) && this.tryHandleInOneLineToken(token, level)) {
347
+ return; // Return early to avoid processing innerTokens
348
+ }
300
349
  else if (this.shouldFormatContainerAsOneline(token, shouldIndentNested) && this.tryHandleOnelineToken(token, level)) {
301
350
  return; // Return early to avoid processing innerTokens
302
351
  }
@@ -384,6 +433,11 @@ class SqlPrinter {
384
433
  if (enteredJoinOnClause) {
385
434
  this.joinOnClauseDepth++;
386
435
  }
436
+ const enteredCommentedFunctionCall = this.shouldExpandCommentedFunctionCall(token);
437
+ if (enteredCommentedFunctionCall) {
438
+ this.commentedFunctionCallDepth++;
439
+ }
440
+ const enteredLogicalOperatorWithComment = this.isLogicalOperatorWithComment(token);
387
441
  for (let i = leadingCommentCount; i < token.innerTokens.length; i++) {
388
442
  const child = token.innerTokens[i];
389
443
  const nextChild = token.innerTokens[i + 1];
@@ -434,7 +488,10 @@ class SqlPrinter {
434
488
  const childCommentContext = child.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.CommentBlock
435
489
  ? { position: 'inline', isTopLevelContainer: containerIsTopLevel }
436
490
  : undefined;
437
- this.appendToken(child, innerLevel, token.containerType, nextCaseContextDepth, childIndentParentActive, childCommentContext, previousChildWasOpenParen);
491
+ const childLevel = enteredCommentedFunctionCall && child.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.ValueList
492
+ ? innerLevel + 1
493
+ : innerLevel;
494
+ this.appendToken(child, childLevel, token.containerType, nextCaseContextDepth, childIndentParentActive, childCommentContext, previousChildWasOpenParen);
438
495
  if (inMergePredicate) {
439
496
  this.mergeWhenPredicateDepth--;
440
497
  }
@@ -442,12 +499,24 @@ class SqlPrinter {
442
499
  mergePredicateActive = false;
443
500
  }
444
501
  }
502
+ if (enteredLogicalOperatorWithComment && !this.isOnelineMode()) {
503
+ const currentLine = this.linePrinter.getCurrentLine();
504
+ if (currentLine.text.trim() === '') {
505
+ currentLine.level = level + 1;
506
+ }
507
+ else {
508
+ this.linePrinter.appendNewline(level + 1);
509
+ }
510
+ }
445
511
  if (this.smartCommentBlockBuilder && this.smartCommentBlockBuilder.mode === 'line') {
446
512
  this.flushSmartCommentBlockBuilder();
447
513
  }
448
514
  if (enteredJoinOnClause) {
449
515
  this.joinOnClauseDepth--;
450
516
  }
517
+ if (enteredCommentedFunctionCall) {
518
+ this.commentedFunctionCallDepth--;
519
+ }
451
520
  // Exit WITH clause context when we finish processing WithClause container
452
521
  if (token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.WithClause && this.withClauseStyle === 'full-oneline') {
453
522
  this.insideWithClause = false;
@@ -475,6 +544,33 @@ class SqlPrinter {
475
544
  return false;
476
545
  }
477
546
  }
547
+ shouldExpandCommentedFunctionCall(token) {
548
+ return this.commentExportMode !== 'none' &&
549
+ token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.FunctionCall &&
550
+ token.innerTokens.some(child => child.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.ValueList &&
551
+ this.containsCommentBlock(child));
552
+ }
553
+ containsCommentBlock(token) {
554
+ if (token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.CommentBlock) {
555
+ return true;
556
+ }
557
+ return token.innerTokens.some(child => this.containsCommentBlock(child));
558
+ }
559
+ containsRenderableCommentBlock(token, context) {
560
+ if (token.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.CommentBlock) {
561
+ return this.shouldRenderComment(token, context);
562
+ }
563
+ return token.innerTokens.some(child => this.containsRenderableCommentBlock(child, context));
564
+ }
565
+ isLogicalOperatorWithComment(token) {
566
+ return this.containsCommentBlock(token) &&
567
+ token.type === SqlPrintToken_1.SqlPrintTokenType.operator &&
568
+ ['and', 'or'].includes(token.text.toLowerCase());
569
+ }
570
+ currentLineEndsWithLogicalOperator() {
571
+ const trimmed = this.linePrinter.getCurrentLine().text.trim().toLowerCase();
572
+ return trimmed === 'and' || trimmed === 'or';
573
+ }
478
574
  isCaseContext(containerType) {
479
575
  switch (containerType) {
480
576
  case SqlPrintToken_1.SqlPrintTokenContainerType.CaseExpression:
@@ -634,6 +730,14 @@ class SqlPrinter {
634
730
  this.linePrinter.appendText(text);
635
731
  }
636
732
  }
733
+ handleArgumentSplitterToken(token, level, parentContainerType) {
734
+ this.linePrinter.appendText(token.text);
735
+ if (this.commentedFunctionCallDepth > 0 &&
736
+ parentContainerType === SqlPrintToken_1.SqlPrintTokenContainerType.ValueList &&
737
+ !this.isOnelineMode()) {
738
+ this.linePrinter.appendNewline(level);
739
+ }
740
+ }
637
741
  handleAndOperatorToken(token, level, parentContainerType, caseContextDepth = 0) {
638
742
  const text = this.applyKeywordCase(token.text);
639
743
  if (caseContextDepth > 0) {
@@ -666,6 +770,12 @@ class SqlPrinter {
666
770
  handleParenthesisToken(token, level, indentParentActive, parentContainerType) {
667
771
  if (token.text === '(') {
668
772
  this.linePrinter.appendText(token.text);
773
+ if (this.commentedFunctionCallDepth > 0 &&
774
+ parentContainerType === SqlPrintToken_1.SqlPrintTokenContainerType.FunctionCall &&
775
+ !this.isOnelineMode()) {
776
+ this.linePrinter.appendNewline(level + 1);
777
+ return;
778
+ }
669
779
  if ((parentContainerType === SqlPrintToken_1.SqlPrintTokenContainerType.InsertClause ||
670
780
  parentContainerType === SqlPrintToken_1.SqlPrintTokenContainerType.MergeInsertAction) &&
671
781
  this.insertColumnsOneLine) {
@@ -684,6 +794,12 @@ class SqlPrinter {
684
794
  return;
685
795
  }
686
796
  if (token.text === ')' && !this.isOnelineMode()) {
797
+ if (this.commentedFunctionCallDepth > 0 &&
798
+ parentContainerType === SqlPrintToken_1.SqlPrintTokenContainerType.FunctionCall) {
799
+ this.linePrinter.appendNewline(level);
800
+ this.linePrinter.appendText(token.text);
801
+ return;
802
+ }
687
803
  if (this.shouldBreakBeforeClosingParen(parentContainerType)) {
688
804
  this.linePrinter.appendNewline(Math.max(level, 0));
689
805
  this.linePrinter.appendText(token.text);
@@ -783,6 +899,32 @@ class SqlPrinter {
783
899
  shouldFormatContainerAsOneline(token, shouldIndentNested) {
784
900
  return this.onelineHelper.shouldFormatContainer(token, shouldIndentNested);
785
901
  }
902
+ isInValueListExpression(token) {
903
+ const parts = this.getInValueListParts(token);
904
+ return parts !== null;
905
+ }
906
+ getInValueListParts(token) {
907
+ if (token.containerType !== SqlPrintToken_1.SqlPrintTokenContainerType.BinaryExpression) {
908
+ return null;
909
+ }
910
+ const significant = token.innerTokens.filter(child => child.type !== SqlPrintToken_1.SqlPrintTokenType.space);
911
+ if (significant.length !== 3) {
912
+ return null;
913
+ }
914
+ const [left, operator, right] = significant;
915
+ const operatorText = operator.text.trim().toLowerCase();
916
+ if (operatorText !== 'in' && operatorText !== 'not in') {
917
+ return null;
918
+ }
919
+ if (right.containerType !== SqlPrintToken_1.SqlPrintTokenContainerType.ParenExpression) {
920
+ return null;
921
+ }
922
+ const valueList = right.innerTokens.find(child => child.containerType === SqlPrintToken_1.SqlPrintTokenContainerType.ValueList);
923
+ if (!valueList) {
924
+ return null;
925
+ }
926
+ return { left, operator, valueList };
927
+ }
786
928
  /**
787
929
  * Detects an INSERT column list that must stay on a single line.
788
930
  */
@@ -797,6 +939,12 @@ class SqlPrinter {
797
939
  if (this.smartCommentBlockBuilder && this.smartCommentBlockBuilder.mode === 'line') {
798
940
  this.flushSmartCommentBlockBuilder();
799
941
  }
942
+ if (this.commentedFunctionCallDepth > 0 &&
943
+ parentContainerType === SqlPrintToken_1.SqlPrintTokenContainerType.ValueList &&
944
+ (previousToken === null || previousToken === void 0 ? void 0 : previousToken.type) === SqlPrintToken_1.SqlPrintTokenType.argumentSplitter &&
945
+ !this.isOnelineMode()) {
946
+ return;
947
+ }
800
948
  const currentLineText = this.linePrinter.getCurrentLine().text;
801
949
  if (this.onelineHelper.shouldSkipInsertClauseSpace(parentContainerType, nextToken, currentLineText)) {
802
950
  return;
@@ -924,7 +1072,12 @@ class SqlPrinter {
924
1072
  }
925
1073
  else {
926
1074
  const content = normalized.lines[0];
927
- const lineText = content ? `-- ${content}` : '--';
1075
+ if (this.shouldFallbackSmartLineCommentToBlock()) {
1076
+ this.linePrinter.appendText(this.buildBlockComment([content], level));
1077
+ this.ensureTrailingSpace();
1078
+ return;
1079
+ }
1080
+ const lineText = this.buildSmartLineComment(content);
928
1081
  if (parentContainerType === SqlPrintToken_1.SqlPrintTokenContainerType.CommentBlock) {
929
1082
  this.linePrinter.appendText(lineText);
930
1083
  this.pendingLineCommentBreak = this.resolveCommentIndentLevel(level, parentContainerType);
@@ -1005,11 +1158,26 @@ class SqlPrinter {
1005
1158
  if (this.commentStyle !== 'smart') {
1006
1159
  const rawLines = this.extractRawCommentBlockLines(token);
1007
1160
  if (rawLines.length > 0) {
1161
+ if (context.position === 'leading' && context.isTopLevelContainer && !this.isOnelineMode()) {
1162
+ for (const line of rawLines) {
1163
+ this.linePrinter.appendText(`/* ${line} */`);
1164
+ this.linePrinter.appendNewline(level);
1165
+ }
1166
+ return;
1167
+ }
1008
1168
  const normalizedBlocks = rawLines.map(line => `/* ${line} */`).join(' ');
1009
1169
  const hasTrailingSpace = (_a = token.innerTokens) === null || _a === void 0 ? void 0 : _a.some(child => child.type === SqlPrintToken_1.SqlPrintTokenType.space && child.text.includes(' '));
1010
1170
  this.linePrinter.appendText(hasTrailingSpace ? `${normalizedBlocks} ` : normalizedBlocks);
1011
1171
  return;
1012
1172
  }
1173
+ const directBlockComments = this.extractDirectBlockCommentTexts(token);
1174
+ if (directBlockComments.length > 1 && context.position === 'leading' && context.isTopLevelContainer && !this.isOnelineMode()) {
1175
+ for (const comment of directBlockComments) {
1176
+ this.linePrinter.appendText(comment);
1177
+ this.linePrinter.appendNewline(level);
1178
+ }
1179
+ return;
1180
+ }
1013
1181
  for (const child of token.innerTokens) {
1014
1182
  // Force inner comment tokens to render once the block is approved.
1015
1183
  const childContext = {
@@ -1021,6 +1189,11 @@ class SqlPrinter {
1021
1189
  }
1022
1190
  return;
1023
1191
  }
1192
+ const emptyBlockCommentText = this.getEmptyBlockCommentText(token);
1193
+ if (emptyBlockCommentText !== null) {
1194
+ this.linePrinter.appendText(emptyBlockCommentText);
1195
+ return;
1196
+ }
1024
1197
  const lines = this.collectCommentBlockLines(token);
1025
1198
  if (lines.length === 0 && !this.smartCommentBlockBuilder) {
1026
1199
  // No meaningful content; treat as empty line comment to preserve spacing
@@ -1042,6 +1215,18 @@ class SqlPrinter {
1042
1215
  this.smartCommentBlockBuilder.lines.push(...lines);
1043
1216
  }
1044
1217
  }
1218
+ getEmptyBlockCommentText(token) {
1219
+ var _a;
1220
+ const commentTokens = ((_a = token.innerTokens) !== null && _a !== void 0 ? _a : []).filter(child => child.type === SqlPrintToken_1.SqlPrintTokenType.comment);
1221
+ if (commentTokens.length !== 1) {
1222
+ return null;
1223
+ }
1224
+ const trimmed = commentTokens[0].text.trim();
1225
+ if (!trimmed.startsWith('/*') || !trimmed.endsWith('*/')) {
1226
+ return null;
1227
+ }
1228
+ return trimmed.slice(2, -2).trim() === '' ? trimmed : null;
1229
+ }
1045
1230
  normalizeSmartBlockLine(raw) {
1046
1231
  // Remove trailing whitespace that only carries formatting artifacts
1047
1232
  let line = raw.replace(/\s+$/g, '');
@@ -1080,14 +1265,16 @@ class SqlPrinter {
1080
1265
  const { lines, level, mode } = this.smartCommentBlockBuilder;
1081
1266
  if (mode === 'line') {
1082
1267
  const meaningfulLineCount = lines.filter(line => line.trim() !== '').length;
1083
- if (meaningfulLineCount > 1) {
1268
+ if (meaningfulLineCount > 1 || this.shouldFallbackSmartLineCommentToBlock()) {
1084
1269
  const blockText = this.buildBlockComment(lines, level);
1085
1270
  this.linePrinter.appendText(blockText);
1271
+ if (this.shouldFallbackSmartLineCommentToBlock()) {
1272
+ this.ensureTrailingSpace();
1273
+ }
1086
1274
  }
1087
1275
  else {
1088
1276
  const content = (_a = lines[0]) !== null && _a !== void 0 ? _a : '';
1089
- const lineText = content ? `-- ${content}` : '--';
1090
- this.linePrinter.appendText(lineText);
1277
+ this.linePrinter.appendText(this.buildSmartLineComment(content));
1091
1278
  }
1092
1279
  if (!this.isOnelineMode()) {
1093
1280
  this.linePrinter.appendNewline(level);
@@ -1096,6 +1283,12 @@ class SqlPrinter {
1096
1283
  }
1097
1284
  this.smartCommentBlockBuilder = null;
1098
1285
  }
1286
+ shouldFallbackSmartLineCommentToBlock() {
1287
+ return this.isOnelineMode();
1288
+ }
1289
+ buildSmartLineComment(content) {
1290
+ return content ? `-- ${content}` : '--';
1291
+ }
1099
1292
  collectCommentBlockLines(token) {
1100
1293
  var _a;
1101
1294
  const lines = [];
@@ -1117,7 +1310,12 @@ class SqlPrinter {
1117
1310
  }
1118
1311
  const content = this.extractLineCommentContent(trimmed);
1119
1312
  if (content !== null) {
1120
- lines.push(content);
1313
+ if (!content && trimmed.startsWith('/*') && trimmed.endsWith('*/')) {
1314
+ lines.push(this.sanitizeCommentLine(this.escapeCommentDelimiters(trimmed)));
1315
+ }
1316
+ else {
1317
+ lines.push(content);
1318
+ }
1121
1319
  }
1122
1320
  }
1123
1321
  }
@@ -1149,6 +1347,20 @@ class SqlPrinter {
1149
1347
  }
1150
1348
  return lines;
1151
1349
  }
1350
+ extractDirectBlockCommentTexts(token) {
1351
+ var _a;
1352
+ const comments = [];
1353
+ for (const child of (_a = token.innerTokens) !== null && _a !== void 0 ? _a : []) {
1354
+ if (child.type !== SqlPrintToken_1.SqlPrintTokenType.comment) {
1355
+ continue;
1356
+ }
1357
+ const trimmed = child.text.trim();
1358
+ if (trimmed.startsWith('/*') && trimmed.endsWith('*/')) {
1359
+ comments.push(trimmed);
1360
+ }
1361
+ }
1362
+ return comments;
1363
+ }
1152
1364
  normalizeCommentForSmart(text) {
1153
1365
  const trimmed = text.trim();
1154
1366
  let source = trimmed;
@@ -1303,6 +1515,10 @@ class SqlPrinter {
1303
1515
  if (parentType === SqlPrintToken_1.SqlPrintTokenContainerType.SelectClause) {
1304
1516
  return true;
1305
1517
  }
1518
+ if (parentType === SqlPrintToken_1.SqlPrintTokenContainerType.OrderByItem ||
1519
+ parentType === SqlPrintToken_1.SqlPrintTokenContainerType.GroupByClause) {
1520
+ return true;
1521
+ }
1306
1522
  if (parentType === SqlPrintToken_1.SqlPrintTokenContainerType.ExplainStatement) {
1307
1523
  // Ensure EXPLAIN targets print header comments on a dedicated line.
1308
1524
  return true;
@@ -1313,6 +1529,13 @@ class SqlPrinter {
1313
1529
  return false;
1314
1530
  }
1315
1531
  getLeadingCommentIndentLevel(parentType, currentLevel) {
1532
+ if (parentType === SqlPrintToken_1.SqlPrintTokenContainerType.SelectItem) {
1533
+ return currentLevel;
1534
+ }
1535
+ if (parentType === SqlPrintToken_1.SqlPrintTokenContainerType.OrderByItem ||
1536
+ parentType === SqlPrintToken_1.SqlPrintTokenContainerType.GroupByClause) {
1537
+ return currentLevel;
1538
+ }
1316
1539
  if (parentType === SqlPrintToken_1.SqlPrintTokenContainerType.TupleExpression) {
1317
1540
  return currentLevel + 1;
1318
1541
  }
@@ -1327,6 +1550,12 @@ class SqlPrinter {
1327
1550
  }
1328
1551
  return currentLevel;
1329
1552
  }
1553
+ shouldKeepLeadingCommentOnCommaLine() {
1554
+ if (this.commaBreak !== 'before') {
1555
+ return false;
1556
+ }
1557
+ return this.linePrinter.getCurrentLine().text.trim() === ',';
1558
+ }
1330
1559
  /**
1331
1560
  * Determines if the printer is in oneliner mode.
1332
1561
  * Oneliner mode uses single spaces instead of actual newlines.
@@ -1335,12 +1564,18 @@ class SqlPrinter {
1335
1564
  return this.newline === ' ';
1336
1565
  }
1337
1566
  normalizeOneLineMaxLength(value) {
1338
- if (value === undefined || !Number.isFinite(value) || value <= 0) {
1567
+ if (value == null || !Number.isFinite(value) || value <= 0) {
1339
1568
  return undefined;
1340
1569
  }
1341
1570
  const normalized = Math.floor(value);
1342
1571
  return normalized > 0 ? normalized : undefined;
1343
1572
  }
1573
+ normalizeKeywordCase(value) {
1574
+ return value === 'preserve' ? 'none' : value !== null && value !== void 0 ? value : 'none';
1575
+ }
1576
+ normalizeJoinOnBreak(value) {
1577
+ return value === 'before' ? 'before' : 'none';
1578
+ }
1344
1579
  fitsOneLineMaxLength(text) {
1345
1580
  if (this.oneLineMaxLength === undefined) {
1346
1581
  return true;
@@ -1354,9 +1589,13 @@ class SqlPrinter {
1354
1589
  * Creates a nested SqlPrinter instance for proper CTE oneline formatting.
1355
1590
  */
1356
1591
  tryHandleCteOnelineToken(token, level) {
1592
+ if (this.shouldPreserveCteComments(token)) {
1593
+ return false;
1594
+ }
1357
1595
  const onelinePrinter = this.createCteOnelinePrinter();
1358
1596
  const onelineResult = onelinePrinter.print(token, level);
1359
1597
  let cleanedResult = this.cleanDuplicateSpaces(onelineResult);
1598
+ // TODO(rawsql-ts#890): replace this CTE-oneline whitespace fallback with a token-level rewrite.
1360
1599
  cleanedResult = cleanedResult.replace(/\(\s+/g, '(').replace(/\s+\)/g, ' )');
1361
1600
  const trimmedResult = cleanedResult.trim();
1362
1601
  if (!this.fitsOneLineMaxLength(trimmedResult)) {
@@ -1365,6 +1604,12 @@ class SqlPrinter {
1365
1604
  this.linePrinter.appendText(trimmedResult);
1366
1605
  return true;
1367
1606
  }
1607
+ shouldPreserveCteComments(token) {
1608
+ return this.containsRenderableCommentBlock(token, {
1609
+ position: 'inline',
1610
+ isTopLevelContainer: false,
1611
+ });
1612
+ }
1368
1613
  /**
1369
1614
  * Creates a SqlPrinter instance configured for CTE oneline formatting.
1370
1615
  */
@@ -1402,6 +1647,59 @@ class SqlPrinter {
1402
1647
  this.linePrinter.appendText(cleanedResult);
1403
1648
  return true;
1404
1649
  }
1650
+ tryHandleInOneLineToken(token, level) {
1651
+ const parts = this.getInValueListParts(token);
1652
+ if (!parts) {
1653
+ return false;
1654
+ }
1655
+ if (this.containsRenderableCommentBlock(parts.valueList, { position: 'inline', isTopLevelContainer: false })) {
1656
+ this.appendExpandedInValueList(parts, token, level);
1657
+ return true;
1658
+ }
1659
+ const onelinePrinter = this.createOnelinePrinter();
1660
+ const onelineResult = onelinePrinter.print(token, level);
1661
+ const cleanedResult = this.cleanDuplicateSpaces(onelineResult);
1662
+ if (this.fitsOneLineMaxLength(cleanedResult)) {
1663
+ this.linePrinter.appendText(cleanedResult);
1664
+ return true;
1665
+ }
1666
+ this.appendExpandedInValueList(parts, token, level);
1667
+ return true;
1668
+ }
1669
+ appendExpandedInValueList(parts, token, level) {
1670
+ this.appendToken(parts.left, level, token.containerType);
1671
+ this.ensureTrailingSpace();
1672
+ this.linePrinter.appendText(this.applyKeywordCase(parts.operator.text));
1673
+ this.ensureTrailingSpace();
1674
+ this.linePrinter.appendText('(');
1675
+ const valueGroups = this.splitValueListItems(parts.valueList);
1676
+ for (let i = 0; i < valueGroups.length; i++) {
1677
+ this.linePrinter.appendNewline(level + 1);
1678
+ if (i > 0) {
1679
+ this.linePrinter.appendText(',');
1680
+ this.ensureTrailingSpace();
1681
+ }
1682
+ for (const valueToken of valueGroups[i]) {
1683
+ this.appendToken(valueToken, level + 1, SqlPrintToken_1.SqlPrintTokenContainerType.ValueList);
1684
+ }
1685
+ }
1686
+ this.linePrinter.appendNewline(level);
1687
+ this.linePrinter.appendText(')');
1688
+ }
1689
+ splitValueListItems(valueList) {
1690
+ const groups = [[]];
1691
+ for (const child of valueList.innerTokens) {
1692
+ if (child.type === SqlPrintToken_1.SqlPrintTokenType.argumentSplitter) {
1693
+ groups.push([]);
1694
+ continue;
1695
+ }
1696
+ if (child.type === SqlPrintToken_1.SqlPrintTokenType.space && groups[groups.length - 1].length === 0) {
1697
+ continue;
1698
+ }
1699
+ groups[groups.length - 1].push(child);
1700
+ }
1701
+ return groups.filter(group => group.length > 0);
1702
+ }
1405
1703
  isBooleanParenExpression(token) {
1406
1704
  if (token.containerType !== SqlPrintToken_1.SqlPrintTokenContainerType.ParenExpression) {
1407
1705
  return false;
@@ -1549,6 +1847,7 @@ class SqlPrinter {
1549
1847
  parenthesesOneLine: false, // Prevent recursive processing (avoid infinite loops)
1550
1848
  betweenOneLine: false, // Prevent recursive processing (avoid infinite loops)
1551
1849
  valuesOneLine: false, // Prevent recursive processing (avoid infinite loops)
1850
+ inOneLine: false, // Prevent recursive processing (avoid infinite loops)
1552
1851
  joinOneLine: false, // Prevent recursive processing (avoid infinite loops)
1553
1852
  caseOneLine: false, // Prevent recursive processing (avoid infinite loops)
1554
1853
  subqueryOneLine: false, // Prevent recursive processing (avoid infinite loops)