@ttsc/lint 0.28.4 → 0.28.5

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.
@@ -187,6 +187,19 @@ func (formatPrintWidth) Check(ctx *Context, node *shimast.Node) {
187
187
  return
188
188
  }
189
189
 
190
+ // Abstain on any uncontrolled reflow target nested below a binary
191
+ // expression. The structured printer does not own BinaryExpression, so
192
+ // independently flattening or breaking its child calls and value literals
193
+ // can change whether the complete binary line fits. The next cascade pass
194
+ // then reverses those child decisions and `ttsc format` oscillates to the
195
+ // 10-pass cap. A destructuring assignment target may skip only its directly
196
+ // owning `=` because the literal printer owns the complete left-hand list and
197
+ // charges the `= value` suffix. Any binary ancestor above that assignment
198
+ // remains uncontrolled.
199
+ if hasUncontrolledBinaryExpressionAncestor(node) {
200
+ return
201
+ }
202
+
190
203
  // Abstain on any node nested inside a template-literal substitution.
191
204
  // Prettier renders `${…}` expressions at printWidth:Infinity, it
192
205
  // never breaks an interpolation the source wrote on one line, so
@@ -505,6 +518,31 @@ func hasReflowAncestor(node *shimast.Node) bool {
505
518
  return false
506
519
  }
507
520
 
521
+ // hasUncontrolledBinaryExpressionAncestor reports whether `node` is a fragment
522
+ // of a binary expression whose layout it cannot own. A destructuring assignment
523
+ // target may skip its owning `=` because the literal printer owns that complete
524
+ // left-hand list, but an enclosing binary expression remains uncontrolled.
525
+ func hasUncontrolledBinaryExpressionAncestor(node *shimast.Node) bool {
526
+ if node == nil {
527
+ return false
528
+ }
529
+ skipOwningAssignment := isDestructuringAssignmentTarget(node)
530
+ child := node
531
+ for parent := node.Parent; parent != nil; parent = parent.Parent {
532
+ if parent.Kind == shimast.KindBinaryExpression {
533
+ expression := parent.AsBinaryExpression()
534
+ if skipOwningAssignment && expression != nil && expression.OperatorToken != nil &&
535
+ expression.OperatorToken.Kind == shimast.KindEqualsToken && expression.Left == child {
536
+ skipOwningAssignment = false
537
+ } else {
538
+ return true
539
+ }
540
+ }
541
+ child = parent
542
+ }
543
+ return false
544
+ }
545
+
508
546
  // hasTemplateSubstitutionAncestor reports whether `node` sits inside a
509
547
  // template-literal substitution (`${…}`). formatPrintWidth abstains
510
548
  // on such nodes: Prettier prints template interpolations at infinite
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttsc/lint",
3
- "version": "0.28.4",
3
+ "version": "0.28.5",
4
4
  "description": "Reference ttsc plugin: ESLint-style lint rules over the TypeScript-Go Program used by the type-check pass.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -37,7 +37,7 @@
37
37
  "@types/node": "^25.3.0",
38
38
  "rimraf": "^6.1.2",
39
39
  "typescript": "^7.0.2",
40
- "ttsc": "0.28.4"
40
+ "ttsc": "0.28.5"
41
41
  },
42
42
  "repository": {
43
43
  "type": "git",