diff --git a/benches/js/lib/gate_counts.ts b/benches/js/lib/gate_counts.ts index 6b13b7638..ae1b1ff4d 100644 --- a/benches/js/lib/gate_counts.ts +++ b/benches/js/lib/gate_counts.ts @@ -210,18 +210,7 @@ export const CORPUS_FORMAT_UNKNOWN_PIN: Record = { */ export const CORPUS_FORMAT_PARTIAL_PIN: Record = { svelte: 1, - // 38 → 36: two reproducible files, `prettier/tests/format/js/test-declarations/ - // test_declarations.js` and `prettier/tests/format/js/preserve-line/parameter-list.js`, - // both of which held a `fill_101_boundary` hunk because tsv broke a test call's callback - // parameters to chase print width. Keeping them flat (conformance_prettier.md §Print Width - // Philosophy, "A test call's name") removes that hunk from both — 26/33 → 12/24 and 18/16 → - // 13/15 diff lines. Neither reaches `match` (the match floor is untouched): what remains - // is unexplained, so both files move partial → `unknown` — a real +2 on that pin. Its - // value still reads 114 because the measured count had drifted to 112: earlier landed - // work fixed two unknowns without a re-pin, unnoticed at this gate's release cadence, and - // the +2 lands exactly back on the pinned value. No other reproducible file moves bucket - // with this change, in any tier. - typescript: 36, + typescript: 37, css: 9 }; diff --git a/crates/tsv_lang/CLAUDE.md b/crates/tsv_lang/CLAUDE.md index 0609c2a93..5e48d618a 100644 --- a/crates/tsv_lang/CLAUDE.md +++ b/crates/tsv_lang/CLAUDE.md @@ -60,7 +60,7 @@ All methods take `&self` (interior mutability via `RefCell`): - Context — `with_context()` - Line suffix — `line_suffix()`, `line_suffix_boundary()`, `break_parent()`, `flush_break()` (flush-scoped: forces only the group the deferred run flushes in) - Convenience — `wrap()`, `parens()`, `brackets()`, `braces()` -- Inspection — `will_break()`, `has_forced_break()` +- Inspection — `will_break()`, `can_break()` - Transforms — `remove_lines()` / `atomize()` — rebuild a subtree with its lines statically flattened (old nodes stay in the arena, unused). **Two operations, not one function with a strength dial**, so pick by which prettier behavior you want: `remove_lines` is prettier's `removeLines` (breakable lines only; hard lines and `MultilineText` survive — it cannot promise one line), while `atomize` emulates a re-render at `printWidth: Infinity` (hard lines deleted, `conditional_group` collapsed to its least-expanded state). Atomizing is only sound where the caller has proved no newline is required — deleting a hard line fuses the content around it. The atomize contract is asserted directly by a width-invariance test: its result must render identically at every width - Diagnostics — `line_comment_text_pooled()` (tags `//` text for the swallow check) diff --git a/crates/tsv_lang/src/doc/arena.rs b/crates/tsv_lang/src/doc/arena.rs index 914dabe77..834f9d072 100644 --- a/crates/tsv_lang/src/doc/arena.rs +++ b/crates/tsv_lang/src/doc/arena.rs @@ -1981,45 +1981,6 @@ impl DocArena { result } - /// Check if a doc has forced breaks (hardlines only, no should_break groups). - pub fn has_forced_break(&self, id: DocId) -> bool { - let nodes = self.nodes.borrow(); - self.has_forced_break_inner(id, &nodes) - } - - fn has_forced_break_inner(&self, id: DocId, nodes: &[DocNode]) -> bool { - match &nodes[id.index()] { - // deliberate asymmetry with `will_break_fill`: this predicate stays blind to - // newline-bearing Text on purpose — it is the "less aggressive" (hardlines-only, - // ignores `should_break`) test for the last-argument hug state in the call/new printers - DocNode::Text(_) => false, - DocNode::MultilineText { .. } => true, - DocNode::Line(kind) => matches!(kind, LineKind::Hard | LineKind::Literal), - DocNode::Indent(inner) | DocNode::Dedent(inner) => { - self.has_forced_break_inner(*inner, nodes) - } - DocNode::AlignRoot { contents, .. } | DocNode::Align { contents, .. } => { - self.has_forced_break_inner(*contents, nodes) - } - DocNode::IndentIfBreak { contents, .. } => { - self.has_forced_break_inner(*contents, nodes) - } - DocNode::Group { contents, .. } => self.has_forced_break_inner(*contents, nodes), - DocNode::IfBreak { .. } => false, - DocNode::Concat(range) | DocNode::Fill(range) => { - let children = self.children.borrow(); - let kids = range.resolve(&children); - kids.iter() - .any(|&kid| self.has_forced_break_inner(kid, nodes)) - } - DocNode::WithContext { doc, .. } => self.has_forced_break_inner(*doc, nodes), - DocNode::LineSuffix(_) => false, - DocNode::LineSuffixBoundary => false, - DocNode::BreakParent => true, - DocNode::FlushBreak => false, - } - } - /// Check if a doc can break (contains any line elements) — Prettier's `canBreak`. /// /// The dual of [`Self::will_break`]: `will_break` asks whether a doc *must* break, diff --git a/crates/tsv_ts/src/printer/calls/call_formatting.rs b/crates/tsv_ts/src/printer/calls/call_formatting.rs index 674e60033..4aa2a7c06 100644 --- a/crates/tsv_ts/src/printer/calls/call_formatting.rs +++ b/crates/tsv_ts/src/printer/calls/call_formatting.rs @@ -23,7 +23,7 @@ use super::arg_wrapping::{ build_inline_args, build_inline_or_expand_all, could_expand_arrow_chain, last_two_args_same_type, prebuild_expand_last_break_body, prebuild_expand_last_obj_array_body, prepend_arrow_body_comments, should_expand_first_arg, try_hug_multiline_template_arg, - wrap_call_with_hard_breaks, wrap_call_with_soft_breaks, + wrap_call_with_hard_breaks, wrap_call_with_soft_breaks, wrap_call_with_will_break_guard, }; use super::call_paren_open; use super::module_paths::{get_module_path_chain_break, is_boolean_call, is_module_path_no_break}; @@ -460,15 +460,26 @@ pub(super) fn build_call_doc_with_wrapping( ); // Prettier: group(contents, { shouldBreak: printedArguments.some(willBreak) }). - // The explicit shouldBreak is redundant here: a forced break anywhere in - // `arg_parts` (a non-empty block body's hardlines, a source-multiline object's - // group_break) already breaks this group at render, so the plain group is the - // same layout. This still handles block functions before the last arg - // (`fn((x) => { body }, aaa)`) without the old has_block_function_before_last - // check, which was too aggressive — it forced hardlines for empty block bodies - // like `async () => {}`, preventing calls like `fn([], 3, async () => {}, aaa)` - // from staying on one line. - wrap_call_with_soft_breaks(d, callee, arg_parts) + // + // The explicit shouldBreak is NOT redundant, though it looks it: a forced break in + // `arg_parts` does break this group at *render* (the plain-group arm keys on + // `should_break || will_break(contents)`), but `arena_fits`' Group arm keys only on + // `should_break` — tsv has no propagateBreaks. So inside an outer FLAT fits walk a + // plain group is measured flat to its first hardline, where a `group_break` is + // entered in Break mode and ends the line at its first softline. Prettier's + // propagateBreaks makes its own fits see such a group broken, i.e. like the + // `group_break` side. The two shapes therefore differ wherever an outer flat fits + // measures this call — a `conditional_group` state, a fill part — and the angle-bracket + // cast ladder is a live observer: without the guard, `fn(a, (y) => { … }, c)` is + // measured short enough to select the parenthesized state, printing `(⏎fn(…)⏎)` + // where prettier keeps the cast attached. See + // `expressions/type_assertion_call_block_arg_long`. + // + // This still handles block functions before the last arg (`fn((x) => { body }, aaa)`) + // without the old has_block_function_before_last check, which was too aggressive — it + // forced hardlines for empty block bodies like `async () => {}`, preventing calls like + // `fn([], 3, async () => {}, aaa)` from staying on one line. + wrap_call_with_will_break_guard(d, callee, arg_parts) } /// Single-argument comment paths: leading line comments (multi-line expansion) diff --git a/crates/tsv_ts/src/printer/calls/new_expression.rs b/crates/tsv_ts/src/printer/calls/new_expression.rs index 6702ee4e6..c1f3e7c9b 100644 --- a/crates/tsv_ts/src/printer/calls/new_expression.rs +++ b/crates/tsv_ts/src/printer/calls/new_expression.rs @@ -711,21 +711,13 @@ impl<'a> Printer<'a> { ); } - // Different types: if last arg has forced breaks, use inline-or-expand-all - // TODO: call_formatting.rs's twin dropped this screen — its 3-state - // conditional_group lands a forced-break last arg on the hug; converging - // needs a `new`-expression fixture pinning that layout first. - if d.has_forced_break(last_arg_doc) { - return build_inline_or_expand_all( - d, - callee_with_types, - &head_parts, - last_arg_doc, - all_args_broken, - ); - } - - // No forced breaks: 3-state (inline → hug → expand all) + // Different types: 3-state (inline → hug → expand all), exactly as + // call_formatting.rs's twin does. Prettier's printCallArguments is shared + // by `new` (its header comment lists NewExpression), and for a breaking + // last arg it keeps the hug: `[breakParent, conditionalGroup([hug, + // allArgsBrokenOut])]` — there is no forced-break → inline-or-expand-all + // form. A last arg carrying its own forced break falls out of state 0 and + // lands on the hug, the same layout for both break kinds. let state_inline = build_inline_args(d, callee_with_types, &head_parts, last_arg_doc); let state_hug = d.concat(&[ diff --git a/tests/fixtures/typescript/expressions/new/expand_last_block_method_long/expected.json b/tests/fixtures/typescript/expressions/new/expand_last_block_method_long/expected.json new file mode 100644 index 000000000..e16bc4d10 --- /dev/null +++ b/tests/fixtures/typescript/expressions/new/expand_last_block_method_long/expected.json @@ -0,0 +1,972 @@ +{ + "css": null, + "js": [], + "start": 0, + "end": 762, + "type": "Root", + "fragment": { + "type": "Fragment", + "nodes": [] + }, + "options": null, + "comments": [ + { + "type": "Line", + "value": " Short: object last arg hugs, method body expands (well under 100)", + "start": 20, + "end": 88, + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 69 + } + } + }, + { + "type": "Line", + "value": " Hug prefix exactly 100: object still hugs — its forced break doesn't push the head out", + "start": 135, + "end": 224, + "loc": { + "start": { + "line": 9, + "column": 1 + }, + "end": { + "line": 9, + "column": 90 + } + } + }, + { + "type": "Line", + "value": " Hug prefix 101: head args no longer fit beside the object, all args expand", + "start": 355, + "end": 432, + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 16, + "column": 78 + } + } + }, + { + "type": "Line", + "value": " Same-shape plain call (control): hugs identically", + "start": 575, + "end": 627, + "loc": { + "start": { + "line": 26, + "column": 1 + }, + "end": { + "line": 26, + "column": 53 + } + } + } + ], + "instance": { + "type": "Script", + "start": 0, + "end": 761, + "context": "default", + "content": { + "type": "Program", + "start": 18, + "end": 752, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 32, + "column": 9 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 90, + "end": 132, + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 7, + "column": 4 + } + }, + "expression": { + "type": "NewExpression", + "start": 90, + "end": 131, + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 7, + "column": 3 + } + }, + "callee": { + "type": "Identifier", + "start": 94, + "end": 97, + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 3, + "column": 8 + } + }, + "name": "Cls" + }, + "arguments": [ + { + "type": "Literal", + "start": 98, + "end": 101, + "loc": { + "start": { + "line": 3, + "column": 9 + }, + "end": { + "line": 3, + "column": 12 + } + }, + "value": "a", + "raw": "'a'" + }, + { + "type": "ObjectExpression", + "start": 103, + "end": 130, + "loc": { + "start": { + "line": 3, + "column": 14 + }, + "end": { + "line": 7, + "column": 2 + } + }, + "properties": [ + { + "type": "Property", + "start": 107, + "end": 127, + "loc": { + "start": { + "line": 4, + "column": 2 + }, + "end": { + "line": 6, + "column": 3 + } + }, + "method": true, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 107, + "end": 109, + "loc": { + "start": { + "line": 4, + "column": 2 + }, + "end": { + "line": 4, + "column": 4 + } + }, + "name": "m1" + }, + "value": { + "type": "FunctionExpression", + "start": 109, + "end": 127, + "loc": { + "start": { + "line": 4, + "column": 4 + }, + "end": { + "line": 6, + "column": 3 + } + }, + "id": null, + "expression": false, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 112, + "end": 127, + "loc": { + "start": { + "line": 4, + "column": 7 + }, + "end": { + "line": 6, + "column": 3 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 117, + "end": 123, + "loc": { + "start": { + "line": 5, + "column": 3 + }, + "end": { + "line": 5, + "column": 9 + } + }, + "expression": { + "type": "CallExpression", + "start": 117, + "end": 122, + "loc": { + "start": { + "line": 5, + "column": 3 + }, + "end": { + "line": 5, + "column": 8 + } + }, + "callee": { + "type": "Identifier", + "start": 117, + "end": 120, + "loc": { + "start": { + "line": 5, + "column": 3 + }, + "end": { + "line": 5, + "column": 6 + } + }, + "name": "fn1" + }, + "arguments": [], + "optional": false + } + } + ] + } + }, + "kind": "init" + } + ] + } + ] + }, + "leadingComments": [ + { + "type": "Line", + "value": " Short: object last arg hugs, method body expands (well under 100)", + "start": 20, + "end": 88 + } + ] + }, + { + "type": "ExpressionStatement", + "start": 226, + "end": 352, + "loc": { + "start": { + "line": 10, + "column": 1 + }, + "end": { + "line": 14, + "column": 4 + } + }, + "expression": { + "type": "NewExpression", + "start": 226, + "end": 351, + "loc": { + "start": { + "line": 10, + "column": 1 + }, + "end": { + "line": 14, + "column": 3 + } + }, + "callee": { + "type": "Identifier", + "start": 230, + "end": 233, + "loc": { + "start": { + "line": 10, + "column": 5 + }, + "end": { + "line": 10, + "column": 8 + } + }, + "name": "Cls" + }, + "arguments": [ + { + "type": "Literal", + "start": 234, + "end": 321, + "loc": { + "start": { + "line": 10, + "column": 9 + }, + "end": { + "line": 10, + "column": 96 + } + }, + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "raw": "'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'" + }, + { + "type": "ObjectExpression", + "start": 323, + "end": 350, + "loc": { + "start": { + "line": 10, + "column": 98 + }, + "end": { + "line": 14, + "column": 2 + } + }, + "properties": [ + { + "type": "Property", + "start": 327, + "end": 347, + "loc": { + "start": { + "line": 11, + "column": 2 + }, + "end": { + "line": 13, + "column": 3 + } + }, + "method": true, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 327, + "end": 329, + "loc": { + "start": { + "line": 11, + "column": 2 + }, + "end": { + "line": 11, + "column": 4 + } + }, + "name": "m2" + }, + "value": { + "type": "FunctionExpression", + "start": 329, + "end": 347, + "loc": { + "start": { + "line": 11, + "column": 4 + }, + "end": { + "line": 13, + "column": 3 + } + }, + "id": null, + "expression": false, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 332, + "end": 347, + "loc": { + "start": { + "line": 11, + "column": 7 + }, + "end": { + "line": 13, + "column": 3 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 337, + "end": 343, + "loc": { + "start": { + "line": 12, + "column": 3 + }, + "end": { + "line": 12, + "column": 9 + } + }, + "expression": { + "type": "CallExpression", + "start": 337, + "end": 342, + "loc": { + "start": { + "line": 12, + "column": 3 + }, + "end": { + "line": 12, + "column": 8 + } + }, + "callee": { + "type": "Identifier", + "start": 337, + "end": 340, + "loc": { + "start": { + "line": 12, + "column": 3 + }, + "end": { + "line": 12, + "column": 6 + } + }, + "name": "fn2" + }, + "arguments": [], + "optional": false + } + } + ] + } + }, + "kind": "init" + } + ] + } + ] + }, + "leadingComments": [ + { + "type": "Line", + "value": " Hug prefix exactly 100: object still hugs — its forced break doesn't push the head out", + "start": 135, + "end": 224 + } + ] + }, + { + "type": "ExpressionStatement", + "start": 434, + "end": 572, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 24, + "column": 3 + } + }, + "expression": { + "type": "NewExpression", + "start": 434, + "end": 571, + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 24, + "column": 2 + } + }, + "callee": { + "type": "Identifier", + "start": 438, + "end": 441, + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 8 + } + }, + "name": "Cls" + }, + "arguments": [ + { + "type": "Literal", + "start": 445, + "end": 533, + "loc": { + "start": { + "line": 18, + "column": 2 + }, + "end": { + "line": 18, + "column": 90 + } + }, + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "raw": "'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'" + }, + { + "type": "ObjectExpression", + "start": 537, + "end": 568, + "loc": { + "start": { + "line": 19, + "column": 2 + }, + "end": { + "line": 23, + "column": 3 + } + }, + "properties": [ + { + "type": "Property", + "start": 542, + "end": 564, + "loc": { + "start": { + "line": 20, + "column": 3 + }, + "end": { + "line": 22, + "column": 4 + } + }, + "method": true, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 542, + "end": 544, + "loc": { + "start": { + "line": 20, + "column": 3 + }, + "end": { + "line": 20, + "column": 5 + } + }, + "name": "m3" + }, + "value": { + "type": "FunctionExpression", + "start": 544, + "end": 564, + "loc": { + "start": { + "line": 20, + "column": 5 + }, + "end": { + "line": 22, + "column": 4 + } + }, + "id": null, + "expression": false, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 547, + "end": 564, + "loc": { + "start": { + "line": 20, + "column": 8 + }, + "end": { + "line": 22, + "column": 4 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 553, + "end": 559, + "loc": { + "start": { + "line": 21, + "column": 4 + }, + "end": { + "line": 21, + "column": 10 + } + }, + "expression": { + "type": "CallExpression", + "start": 553, + "end": 558, + "loc": { + "start": { + "line": 21, + "column": 4 + }, + "end": { + "line": 21, + "column": 9 + } + }, + "callee": { + "type": "Identifier", + "start": 553, + "end": 556, + "loc": { + "start": { + "line": 21, + "column": 4 + }, + "end": { + "line": 21, + "column": 7 + } + }, + "name": "fn3" + }, + "arguments": [], + "optional": false + } + } + ] + } + }, + "kind": "init" + } + ] + } + ] + }, + "leadingComments": [ + { + "type": "Line", + "value": " Hug prefix 101: head args no longer fit beside the object, all args expand", + "start": 355, + "end": 432 + } + ] + }, + { + "type": "ExpressionStatement", + "start": 629, + "end": 751, + "loc": { + "start": { + "line": 27, + "column": 1 + }, + "end": { + "line": 31, + "column": 4 + } + }, + "expression": { + "type": "CallExpression", + "start": 629, + "end": 750, + "loc": { + "start": { + "line": 27, + "column": 1 + }, + "end": { + "line": 31, + "column": 3 + } + }, + "callee": { + "type": "Identifier", + "start": 629, + "end": 632, + "loc": { + "start": { + "line": 27, + "column": 1 + }, + "end": { + "line": 27, + "column": 4 + } + }, + "name": "fn4" + }, + "arguments": [ + { + "type": "Literal", + "start": 633, + "end": 720, + "loc": { + "start": { + "line": 27, + "column": 5 + }, + "end": { + "line": 27, + "column": 92 + } + }, + "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "raw": "'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'" + }, + { + "type": "ObjectExpression", + "start": 722, + "end": 749, + "loc": { + "start": { + "line": 27, + "column": 94 + }, + "end": { + "line": 31, + "column": 2 + } + }, + "properties": [ + { + "type": "Property", + "start": 726, + "end": 746, + "loc": { + "start": { + "line": 28, + "column": 2 + }, + "end": { + "line": 30, + "column": 3 + } + }, + "method": true, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 726, + "end": 728, + "loc": { + "start": { + "line": 28, + "column": 2 + }, + "end": { + "line": 28, + "column": 4 + } + }, + "name": "m4" + }, + "value": { + "type": "FunctionExpression", + "start": 728, + "end": 746, + "loc": { + "start": { + "line": 28, + "column": 4 + }, + "end": { + "line": 30, + "column": 3 + } + }, + "id": null, + "expression": false, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 731, + "end": 746, + "loc": { + "start": { + "line": 28, + "column": 7 + }, + "end": { + "line": 30, + "column": 3 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 736, + "end": 742, + "loc": { + "start": { + "line": 29, + "column": 3 + }, + "end": { + "line": 29, + "column": 9 + } + }, + "expression": { + "type": "CallExpression", + "start": 736, + "end": 741, + "loc": { + "start": { + "line": 29, + "column": 3 + }, + "end": { + "line": 29, + "column": 8 + } + }, + "callee": { + "type": "Identifier", + "start": 736, + "end": 739, + "loc": { + "start": { + "line": 29, + "column": 3 + }, + "end": { + "line": 29, + "column": 6 + } + }, + "name": "fn5" + }, + "arguments": [], + "optional": false + } + } + ] + } + }, + "kind": "init" + } + ] + } + ], + "optional": false + }, + "leadingComments": [ + { + "type": "Line", + "value": " Same-shape plain call (control): hugs identically", + "start": 575, + "end": 627 + } + ] + } + ], + "sourceType": "module" + }, + "attributes": [ + { + "type": "Attribute", + "start": 8, + "end": 17, + "name": "lang", + "name_loc": { + "start": { + "line": 1, + "column": 8, + "character": 8 + }, + "end": { + "line": 1, + "column": 12, + "character": 12 + } + }, + "value": [ + { + "start": 14, + "end": 16, + "type": "Text", + "raw": "ts", + "data": "ts" + } + ] + } + ] + } +} diff --git a/tests/fixtures/typescript/expressions/new/expand_last_block_method_long/input.svelte b/tests/fixtures/typescript/expressions/new/expand_last_block_method_long/input.svelte new file mode 100644 index 000000000..f81388780 --- /dev/null +++ b/tests/fixtures/typescript/expressions/new/expand_last_block_method_long/input.svelte @@ -0,0 +1,32 @@ + diff --git a/tests/fixtures/typescript/expressions/new/expand_last_block_method_long/unformatted_compact.svelte b/tests/fixtures/typescript/expressions/new/expand_last_block_method_long/unformatted_compact.svelte new file mode 100644 index 000000000..d7e89014d --- /dev/null +++ b/tests/fixtures/typescript/expressions/new/expand_last_block_method_long/unformatted_compact.svelte @@ -0,0 +1,13 @@ + diff --git a/tests/fixtures/typescript/expressions/type_assertion_call_block_arg_long/expected.json b/tests/fixtures/typescript/expressions/type_assertion_call_block_arg_long/expected.json new file mode 100644 index 000000000..ba1dd9b35 --- /dev/null +++ b/tests/fixtures/typescript/expressions/type_assertion_call_block_arg_long/expected.json @@ -0,0 +1,870 @@ +{ + "css": null, + "js": [], + "start": 0, + "end": 684, + "type": "Root", + "fragment": { + "type": "Fragment", + "nodes": [] + }, + "options": null, + "comments": [ + { + "type": "Line", + "value": " Short: cast stays attached, call breaks internally (a block-body arg always breaks it)", + "start": 20, + "end": 109, + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 90 + } + } + }, + { + "type": "Line", + "value": " Prefix to the block body exactly 100: cast attached, args expand", + "start": 160, + "end": 227, + "loc": { + "start": { + "line": 11, + "column": 1 + }, + "end": { + "line": 11, + "column": 68 + } + } + }, + { + "type": "Line", + "value": " Prefix to the block body at 101: same layout — the width up to the arg", + "start": 358, + "end": 431, + "loc": { + "start": { + "line": 20, + "column": 1 + }, + "end": { + "line": 20, + "column": 74 + } + } + }, + { + "type": "Line", + "value": " list's own break never decides the cast, so the call still breaks", + "start": 433, + "end": 501, + "loc": { + "start": { + "line": 21, + "column": 1 + }, + "end": { + "line": 21, + "column": 69 + } + } + }, + { + "type": "Line", + "value": " internally and the cast stays attached", + "start": 503, + "end": 544, + "loc": { + "start": { + "line": 22, + "column": 1 + }, + "end": { + "line": 22, + "column": 42 + } + } + } + ], + "instance": { + "type": "Script", + "start": 0, + "end": 683, + "context": "default", + "content": { + "type": "Program", + "start": 18, + "end": 674, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 30, + "column": 9 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 111, + "end": 157, + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 9, + "column": 3 + } + }, + "expression": { + "type": "TSTypeAssertion", + "start": 111, + "end": 156, + "loc": { + "start": { + "line": 3, + "column": 1 + }, + "end": { + "line": 9, + "column": 2 + } + }, + "typeAnnotation": { + "type": "TSTypeReference", + "start": 112, + "end": 113, + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 3 + } + }, + "typeName": { + "type": "Identifier", + "start": 112, + "end": 113, + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 3 + } + }, + "name": "A" + } + }, + "expression": { + "type": "CallExpression", + "start": 114, + "end": 156, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 9, + "column": 2 + } + }, + "callee": { + "type": "Identifier", + "start": 114, + "end": 117, + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 7 + } + }, + "name": "fn1" + }, + "arguments": [ + { + "type": "Identifier", + "start": 121, + "end": 122, + "loc": { + "start": { + "line": 4, + "column": 2 + }, + "end": { + "line": 4, + "column": 3 + } + }, + "name": "b" + }, + { + "type": "ArrowFunctionExpression", + "start": 126, + "end": 148, + "loc": { + "start": { + "line": 5, + "column": 2 + }, + "end": { + "line": 7, + "column": 3 + } + }, + "id": null, + "expression": false, + "generator": false, + "async": false, + "params": [ + { + "type": "Identifier", + "start": 127, + "end": 128, + "loc": { + "start": { + "line": 5, + "column": 3 + }, + "end": { + "line": 5, + "column": 4 + } + }, + "name": "y" + } + ], + "body": { + "type": "BlockStatement", + "start": 133, + "end": 148, + "loc": { + "start": { + "line": 5, + "column": 9 + }, + "end": { + "line": 7, + "column": 3 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 138, + "end": 144, + "loc": { + "start": { + "line": 6, + "column": 3 + }, + "end": { + "line": 6, + "column": 9 + } + }, + "expression": { + "type": "CallExpression", + "start": 138, + "end": 143, + "loc": { + "start": { + "line": 6, + "column": 3 + }, + "end": { + "line": 6, + "column": 8 + } + }, + "callee": { + "type": "Identifier", + "start": 138, + "end": 141, + "loc": { + "start": { + "line": 6, + "column": 3 + }, + "end": { + "line": 6, + "column": 6 + } + }, + "name": "fn2" + }, + "arguments": [], + "optional": false + } + } + ] + } + }, + { + "type": "Identifier", + "start": 152, + "end": 153, + "loc": { + "start": { + "line": 8, + "column": 2 + }, + "end": { + "line": 8, + "column": 3 + } + }, + "name": "c" + } + ], + "optional": false + } + }, + "leadingComments": [ + { + "type": "Line", + "value": " Short: cast stays attached, call breaks internally (a block-body arg always breaks it)", + "start": 20, + "end": 109 + } + ] + }, + { + "type": "ExpressionStatement", + "start": 229, + "end": 355, + "loc": { + "start": { + "line": 12, + "column": 1 + }, + "end": { + "line": 18, + "column": 3 + } + }, + "expression": { + "type": "TSTypeAssertion", + "start": 229, + "end": 354, + "loc": { + "start": { + "line": 12, + "column": 1 + }, + "end": { + "line": 18, + "column": 2 + } + }, + "typeAnnotation": { + "type": "TSTypeReference", + "start": 230, + "end": 231, + "loc": { + "start": { + "line": 12, + "column": 2 + }, + "end": { + "line": 12, + "column": 3 + } + }, + "typeName": { + "type": "Identifier", + "start": 230, + "end": 231, + "loc": { + "start": { + "line": 12, + "column": 2 + }, + "end": { + "line": 12, + "column": 3 + } + }, + "name": "A" + } + }, + "expression": { + "type": "CallExpression", + "start": 232, + "end": 354, + "loc": { + "start": { + "line": 12, + "column": 4 + }, + "end": { + "line": 18, + "column": 2 + } + }, + "callee": { + "type": "Identifier", + "start": 232, + "end": 235, + "loc": { + "start": { + "line": 12, + "column": 4 + }, + "end": { + "line": 12, + "column": 7 + } + }, + "name": "fn3" + }, + "arguments": [ + { + "type": "Identifier", + "start": 239, + "end": 320, + "loc": { + "start": { + "line": 13, + "column": 2 + }, + "end": { + "line": 13, + "column": 83 + } + }, + "name": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "type": "ArrowFunctionExpression", + "start": 324, + "end": 346, + "loc": { + "start": { + "line": 14, + "column": 2 + }, + "end": { + "line": 16, + "column": 3 + } + }, + "id": null, + "expression": false, + "generator": false, + "async": false, + "params": [ + { + "type": "Identifier", + "start": 325, + "end": 326, + "loc": { + "start": { + "line": 14, + "column": 3 + }, + "end": { + "line": 14, + "column": 4 + } + }, + "name": "y" + } + ], + "body": { + "type": "BlockStatement", + "start": 331, + "end": 346, + "loc": { + "start": { + "line": 14, + "column": 9 + }, + "end": { + "line": 16, + "column": 3 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 336, + "end": 342, + "loc": { + "start": { + "line": 15, + "column": 3 + }, + "end": { + "line": 15, + "column": 9 + } + }, + "expression": { + "type": "CallExpression", + "start": 336, + "end": 341, + "loc": { + "start": { + "line": 15, + "column": 3 + }, + "end": { + "line": 15, + "column": 8 + } + }, + "callee": { + "type": "Identifier", + "start": 336, + "end": 339, + "loc": { + "start": { + "line": 15, + "column": 3 + }, + "end": { + "line": 15, + "column": 6 + } + }, + "name": "fn4" + }, + "arguments": [], + "optional": false + } + } + ] + } + }, + { + "type": "Identifier", + "start": 350, + "end": 351, + "loc": { + "start": { + "line": 17, + "column": 2 + }, + "end": { + "line": 17, + "column": 3 + } + }, + "name": "c" + } + ], + "optional": false + } + }, + "leadingComments": [ + { + "type": "Line", + "value": " Prefix to the block body exactly 100: cast attached, args expand", + "start": 160, + "end": 227 + } + ] + }, + { + "type": "ExpressionStatement", + "start": 546, + "end": 673, + "loc": { + "start": { + "line": 23, + "column": 1 + }, + "end": { + "line": 29, + "column": 3 + } + }, + "expression": { + "type": "TSTypeAssertion", + "start": 546, + "end": 672, + "loc": { + "start": { + "line": 23, + "column": 1 + }, + "end": { + "line": 29, + "column": 2 + } + }, + "typeAnnotation": { + "type": "TSTypeReference", + "start": 547, + "end": 548, + "loc": { + "start": { + "line": 23, + "column": 2 + }, + "end": { + "line": 23, + "column": 3 + } + }, + "typeName": { + "type": "Identifier", + "start": 547, + "end": 548, + "loc": { + "start": { + "line": 23, + "column": 2 + }, + "end": { + "line": 23, + "column": 3 + } + }, + "name": "A" + } + }, + "expression": { + "type": "CallExpression", + "start": 549, + "end": 672, + "loc": { + "start": { + "line": 23, + "column": 4 + }, + "end": { + "line": 29, + "column": 2 + } + }, + "callee": { + "type": "Identifier", + "start": 549, + "end": 552, + "loc": { + "start": { + "line": 23, + "column": 4 + }, + "end": { + "line": 23, + "column": 7 + } + }, + "name": "fn5" + }, + "arguments": [ + { + "type": "Identifier", + "start": 556, + "end": 638, + "loc": { + "start": { + "line": 24, + "column": 2 + }, + "end": { + "line": 24, + "column": 84 + } + }, + "name": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + }, + { + "type": "ArrowFunctionExpression", + "start": 642, + "end": 664, + "loc": { + "start": { + "line": 25, + "column": 2 + }, + "end": { + "line": 27, + "column": 3 + } + }, + "id": null, + "expression": false, + "generator": false, + "async": false, + "params": [ + { + "type": "Identifier", + "start": 643, + "end": 644, + "loc": { + "start": { + "line": 25, + "column": 3 + }, + "end": { + "line": 25, + "column": 4 + } + }, + "name": "y" + } + ], + "body": { + "type": "BlockStatement", + "start": 649, + "end": 664, + "loc": { + "start": { + "line": 25, + "column": 9 + }, + "end": { + "line": 27, + "column": 3 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 654, + "end": 660, + "loc": { + "start": { + "line": 26, + "column": 3 + }, + "end": { + "line": 26, + "column": 9 + } + }, + "expression": { + "type": "CallExpression", + "start": 654, + "end": 659, + "loc": { + "start": { + "line": 26, + "column": 3 + }, + "end": { + "line": 26, + "column": 8 + } + }, + "callee": { + "type": "Identifier", + "start": 654, + "end": 657, + "loc": { + "start": { + "line": 26, + "column": 3 + }, + "end": { + "line": 26, + "column": 6 + } + }, + "name": "fn6" + }, + "arguments": [], + "optional": false + } + } + ] + } + }, + { + "type": "Identifier", + "start": 668, + "end": 669, + "loc": { + "start": { + "line": 28, + "column": 2 + }, + "end": { + "line": 28, + "column": 3 + } + }, + "name": "c" + } + ], + "optional": false + } + }, + "leadingComments": [ + { + "type": "Line", + "value": " Prefix to the block body at 101: same layout — the width up to the arg", + "start": 358, + "end": 431 + }, + { + "type": "Line", + "value": " list's own break never decides the cast, so the call still breaks", + "start": 433, + "end": 501 + }, + { + "type": "Line", + "value": " internally and the cast stays attached", + "start": 503, + "end": 544 + } + ] + } + ], + "sourceType": "module" + }, + "attributes": [ + { + "type": "Attribute", + "start": 8, + "end": 17, + "name": "lang", + "name_loc": { + "start": { + "line": 1, + "column": 8, + "character": 8 + }, + "end": { + "line": 1, + "column": 12, + "character": 12 + } + }, + "value": [ + { + "start": 14, + "end": 16, + "type": "Text", + "raw": "ts", + "data": "ts" + } + ] + } + ] + } +} diff --git a/tests/fixtures/typescript/expressions/type_assertion_call_block_arg_long/input.svelte b/tests/fixtures/typescript/expressions/type_assertion_call_block_arg_long/input.svelte new file mode 100644 index 000000000..0070e7d2a --- /dev/null +++ b/tests/fixtures/typescript/expressions/type_assertion_call_block_arg_long/input.svelte @@ -0,0 +1,30 @@ +