From 4c074026fb87f2073fbce9eb630248d9210d177b Mon Sep 17 00:00:00 2001 From: ketan0 Date: Tue, 22 Sep 2026 17:30:48 -0700 Subject: [PATCH] Group unchanged stretches whose folds are unpaired When the structural matcher exceeds diff.graph_limit, the parse's folds stand but are all unpaired, so no stretch matches fold for fold. The context plugin only grouped a stretch's siblings when both sides matched one for one, so each member collapsed on its own: dozens of back-to-back "N unchanged lines" rows, and every fold collapsed on the lhs alone while the rhs kept it open. When the shapes differ, a part now groups with the rhs part over the same lines of the stretch, if that part has two or more siblings whose folds hide only the stretch. Both runs are wrapped in one join, so the two groups share a fold state and consumers that pair folds by fold state render them as one band. Members keep their visibility, so opening a group reveals code directly. A fold that no lhs region shares a fold state with and that is not grouped now collapses on the rhs by itself. Matched stretches take the same path as before. On review's local-data.ts at 48a9385a..82e40383 (too_complex), lhs lines 131-1030 go from 69 collapsed regions, 42 without an rhs partner, to one group paired across sides. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01WbJh11mqHtrFZS7zP2peyf --- plugins/context/src/lib.rs | 164 ++++++++++++++++++++++++++-------- plugins/summarize/plugin.wasm | Bin 568784 -> 568806 bytes src/plugin/tests/context.rs | 152 ++++++++++++++++++++++++++++++- 3 files changed, 275 insertions(+), 41 deletions(-) diff --git a/plugins/context/src/lib.rs b/plugins/context/src/lib.rs index 5497a9ea0..9881176fd 100644 --- a/plugins/context/src/lib.rs +++ b/plugins/context/src/lib.rs @@ -15,11 +15,15 @@ //! stretch; a shorter sliver stays open. When a part spans several //! siblings, only their enclosing group collapses into one row on each side, //! provided the two sides' siblings match one for one: leaves sharing an -//! `alignment_id`, or folds sharing a fold state. A fold in it collapses only when every -//! region on the other side in its fold state lies wholly inside the -//! stretch there, so no fold is hidden on one side while it holds changed -//! lines on the other, such as a matched function that moved elsewhere. -//! Both folds of a matched pair are labelled with their line count. +//! `alignment_id`, or folds sharing a fold state. When they do not, as after +//! a line diff fallback, whose folds are all unpaired, the part is grouped +//! with the other side's part over the same lines, if there is one of two or +//! more siblings; the two groups share a fold state all the same. A fold in +//! it collapses only when every region on the other side in its fold state +//! lies wholly inside the stretch there, so no fold is hidden on one side +//! while it holds changed lines on the other, such as a matched function +//! that moved elsewhere. Both folds of a matched pair are labelled with +//! their line count, and a fold with no partner collapses on its own side. use diffr_plugin_sdk::{ anyhow, export, has_tag, is_fold, walk, Draft, FileEntry, Move, Node, Pairing, Plugin, Region, Source, @@ -69,7 +73,6 @@ fn scope_rows(source: &Source, changed: &BTreeSet) -> BTreeSet { /// One leaf, as far as context cares. struct Leaf { - id: u32, alignment: u32, start: u32, end: u32, @@ -88,7 +91,6 @@ fn leaves(regions: &[Region], other: &BTreeSet) -> Vec { } = ®ion.node { out.push(Leaf { - id: region.id, alignment: *alignment_id, start: region.range.start.line, end: region.range.end.line, @@ -337,8 +339,14 @@ impl Plugin for Context { } let mut lhs_states: BTreeMap = BTreeMap::new(); + // The lhs regions in each fold state, by id. + let mut lhs_by_state: BTreeMap> = BTreeMap::new(); walk(&lhs.regions, &mut |region| { lhs_states.insert(region.id, region.fold_state_id); + lhs_by_state + .entry(region.fold_state_id) + .or_default() + .push(region.id); }); // The rhs regions in each fold state, by id. let mut rhs_by_state: BTreeMap> = BTreeMap::new(); @@ -348,11 +356,6 @@ impl Plugin for Context { .or_default() .push(region.id); }); - // The rhs leaf paired with each lhs leaf, by id. - let rhs_leaf_ids: BTreeMap = lhs_leaves - .iter() - .filter_map(|leaf| Some((leaf.id, rhs_by_alignment.get(&leaf.alignment)?.id))) - .collect(); // Stretches are shaped in reverse document order, so a cut leaf's id // still names the piece that starts where the leaf did. let mut draft = Draft::new(sides); @@ -372,21 +375,55 @@ impl Plugin for Context { .collect() }; let same_shape = key(&lhs_parts) == key(&rhs_parts); + // The first line and line count of each part, relative to the + // stretch, which the parts cover in order. + let spans = |parts: &[Vec]| -> Vec<(u32, u32)> { + let mut at = 0; + parts + .iter() + .map(|part| { + let lines: u32 = part.iter().map(Member::lines).sum(); + at += lines; + (at - lines, lines) + }) + .collect() + }; + let (lhs_spans, rhs_spans) = (spans(&lhs_parts), spans(&rhs_parts)); + // The leaves a part cuts, by alignment and first line, which a + // leaf and the leaf paired with it share. + let cuts = |part: &[Member]| -> Vec<(u32, u32)> { + part.iter() + .filter_map(|member| match member { + Member::Part { + alignment, start, .. + } => Some((*alignment, *start)), + Member::Whole { .. } => None, + }) + .collect() + }; + let whole = |parts: &[Vec]| -> BTreeSet { + parts + .iter() + .flatten() + .filter_map(|member| match member { + Member::Whole { id, .. } => Some(*id), + Member::Part { .. } => None, + }) + .collect() + }; // A fold may collapse when everything its collapse reaches on the - // rhs hides only these unchanged lines. - let rhs_whole: BTreeSet = rhs_parts - .iter() - .flatten() - .filter_map(|member| match member { - Member::Whole { id, .. } => Some(*id), - Member::Part { .. } => None, - }) - .collect(); + // other side hides only these unchanged lines. + let (lhs_whole, rhs_whole) = (whole(&lhs_parts), whole(&rhs_parts)); let hides_only_this = |id: u32| { rhs_by_state .get(&lhs_states[&id]) .is_none_or(|ids| ids.iter().all(|id| rhs_whole.contains(id))) }; + let rhs_hides_only_this = |state: u32| { + lhs_by_state + .get(&state) + .is_none_or(|ids| ids.iter().all(|id| lhs_whole.contains(id))) + }; // Line counts of the rhs folds wholly in the stretch, so each // side's fold takes its own label. let rhs_fold_lines: BTreeMap = rhs_parts @@ -402,14 +439,37 @@ impl Plugin for Context { _ => None, }) .collect(); + // The rhs parts grouped with an lhs part. + let mut partnered = BTreeSet::new(); for (index, part) in lhs_parts.iter().enumerate().rev() { let lines: u32 = part.iter().map(Member::lines).sum(); if lines < MIN_GAP && lines != total { continue; } + // The rhs part grouped with this one: the part it matches, or, + // when the sides' folds do not match, as after a line diff + // fallback, the part over the same lines. Both groups are + // made in one join, so they share a fold state. + let partner = if same_shape { + Some(index) + } else { + rhs_spans + .iter() + .position(|span| *span == lhs_spans[index]) + .filter(|&other| { + rhs_parts[other].len() >= 2 + && cuts(&rhs_parts[other]) == cuts(part) + && rhs_parts[other].iter().all(|member| match member { + Member::Whole { + state: Some(state), .. + } => rhs_hides_only_this(*state), + _ => true, + }) + }) + }; // One context fold is enough for a group. Leave its members' // visibility intact so expanding it reveals code directly. - let grouped = same_shape + let grouped = partner.is_some() && part.len() >= 2 && part.iter().all(|member| match member { Member::Whole { @@ -418,8 +478,9 @@ impl Plugin for Context { _ => true, }); let mut members = Vec::new(); - // The rhs leaves and pieces the lhs members pair with. - let mut rhs_members = Vec::new(); + // The pieces cut from leaves, by their alignment and first + // line, which the rhs piece of each shares. + let mut pieces = BTreeMap::new(); for member in part.iter().rev() { match member { Member::Whole { @@ -433,7 +494,6 @@ impl Plugin for Context { } members.push(*id); let Some(state) = state else { - rhs_members.extend(rhs_leaf_ids.get(id)); continue; }; for rhs_id in rhs_by_state.get(state).into_iter().flatten() { @@ -444,28 +504,56 @@ impl Plugin for Context { } } } - Member::Part { id, start, end, .. } => { + Member::Part { + id, + alignment, + start, + end, + } => { let piece = draft.cut_lines(*id, *start, *end)?; if !grouped { draft.collapse(piece, unchanged_label(end - start))?; } members.push(piece); - rhs_members.extend(draft.paired_leaf(piece)?); + pieces.insert((*alignment, *start), piece); } } } // A fold left open breaks the run, so nothing is grouped. - if grouped { - members.reverse(); - // The rhs leaves and pieces, then the rhs folds. - members.extend(rhs_members); - members.extend(rhs_parts[index].iter().filter_map(|member| match member { - Member::Whole { - id, state: Some(_), .. - } => Some(*id), - _ => None, - })); - draft.group(members, unchanged_label(lines))?; + let Some(partner) = partner.filter(|_| grouped) else { + continue; + }; + partnered.insert(partner); + members.reverse(); + for member in &rhs_parts[partner] { + match member { + Member::Whole { id, .. } => members.push(*id), + Member::Part { + alignment, start, .. + } => members.extend(draft.paired_leaf(pieces[&(*alignment, *start)])?), + } + } + draft.group(members, unchanged_label(lines))?; + } + // A fold only the rhs holds collapses on its own: no lhs fold + // shares its fold state to collapse it with. + for (index, part) in rhs_parts.iter().enumerate() { + let lines: u32 = part.iter().map(Member::lines).sum(); + if partnered.contains(&index) || (lines < MIN_GAP && lines != total) { + continue; + } + for member in part { + if let Member::Whole { + id, + lines, + state: Some(state), + .. + } = member + { + if !lhs_by_state.contains_key(state) { + draft.collapse(*id, unchanged_label(*lines))?; + } + } } } } diff --git a/plugins/summarize/plugin.wasm b/plugins/summarize/plugin.wasm index 1a575b1c3a73f8930640e825e005ab322e25fbc0..e2b9432c1e5c32f35a273a34d3bf1422f5531e92 100644 GIT binary patch delta 54390 zcmeFacUVGsSkTtiS)YB^pes4jZpOV{HY? zHDE_+OT(Lm?0n_idJp`e-#2|-PSaYVijh1+O9@;75#Rne=!dTc4;a>`-$0kM)Z?38 z|LWJ{hu*yg3>fr{%T38OlMxpyaeqsOS8ZgiQtiuD&04l-+x+t`UwqR3(;r9v+$vSw@%8Sh|RgrsL=sI-ZWAZ^&!%h&&-<=>!^0 zpOT1YWGbCbv&jqcl1!t2ktsBWz9P@beEJ7H&6bc`{3hQ@Q|V5+iS3|&vp4K5d&N>{ z4tveA*%qqM^St9<(ktniG>y$fM3%(Oko$; zW_E?0V^7%=mKDLSvP*0y+s;y0GTX||vQDG;SRT#C@hCo;KVyHfi|hs)!^iV?>>7*Y z*V!#Lk;m|d><+ufrtnNQiBIK^*==@{P3F`1BX*xXV0T#@U(Q$YwR|N%#^d=qzL6*J z<9q^HMwXLvdf-L{VsWt$^X)N_kuEOo{+KEm6^XyCF=uv1x`bmKC&8QR&kHtJH!}DqDzE4!5|NpWBL5u1b<^pH!}ae@9iWOE%kfR4#_UFIKMR znJBQixT~$CBo?VMlwk3+sv&ZMipQL6+gY^|-4JPeTs4r4vw2r53buRm*&8yHLG7*>0;)<0xW(QzJyqGO(Ag`58$`jI8-HkyDL4 z8dloP(LY{mMs zf48sw3I1JF`*X~BQTs=#M8c=NrSdkY^Ahu?)ompwXjqeMSL^m7skXFwP04fHr`Iay zXQ9-?!t~yp6$J&JYdy@bj*NvG1CSV2zdRwQRCKG(32MzrwpT6N(NlVBl^c2?0~IXSNE4X2M)T)`BY9#8mt|zBn zP&s?l7SX!99I2I@x7}#H&9f#CXv#Uk3r4q+=Nvdi#XuZ>6`Lzbyo1 zafa>MwR&{bHCu`6#cjKLmLks+@AOO{fw{qPZ1dtt-14tr5|9T>a)9Zb%joUr=u4Gv z8h6aHdAFYjLdC88nJ?TBwLD9JH zwvrM$zqmDy2>WPH9-wN{)~l}%xn>*Q*AjY3aBu= zA;?u7#1=3hpi^uv_>aoV`vPESY5u${zHAHpCBW8qkR@@~0RQ&{so=-JD+<34D6q8~AQW!M?|uXFNa1_( zZJ=d#Tb`hC>WYr`qcz?qBr))p7P)%XGBM>>_gp!3Y|`%?HPZ5^-Uo)nHvRWqa;i>_ zty@HWIYUcaw(W`tFj#ow-zU6ttI;RuzXm=lXloK#6-~gf$N++Dj)@Y2zalEo&mr29 zH37B6)e!9~QT^>5xt!Q>^fo3(Ued(aM&<>Si_sGr*L0~TR=Z3SYpem@ZCrpHb6KzZ zD<&e1#G-KlhNUsI-iiHUJnQ_^@pO^~&Cp!7&7EGy_VxH#*wbg@g`}06&~7e7lslaD{#01SsE%su0C4BS$u4N#}qb(Q_wl?AIOGvhLZ&R!^FWE zuk6hv9II20i%Jlmlxu?gAZn4U9_Vga zn1!3OZR@YsE-?P4C~vR?!4iYi|2*t+4L#%MrSY~$jB?Zr-=(2EoI#(hTuGqjW;!OTK+*CIhL zu(e&`C#UL(!~rWdkhWK~RPHHFvR;_4&PFAWA6XxUc&$MMAw;CgJo61(pHHva3g!9*X{WLY3>1uWkG423VG}`bR7qvSuiGn0Rx|NP>wT@jsC6EfEJ zd|g}o+jxCTGB$D2`eGt$^@g+LapI^11>Nh!I-8EtptHF=5Q~fTv7~qOj$UFbmwcHl zw7G7sMiwU4+q{F28@4yfh+?{3|%9H_>V$}|BQrs}`wTr{zr0wv+&5Q_=@$MK2Y2O}xD zX`6AlB)M+ee7Gs%cyo9uR$G*Aaf`Vwq)_#c52WwRha)lm#Kby#_R9N#Q+m{z7$tgzS(Zx<~^F^z;fFuN-ERqV^zP=QSm1bQUMG%GGmC3~a zfC?_u$VDt@h&4m2|J>H4XItB(Yt7WvSv^~^>&?7%Cfi-$nZgA|zrOf&v4%sXw3WT( zt^F!+$Bx%n8z;WHUWFCNdOyGJtrz^uIX6_TGwcC+f;#W>6nNSTvNb{tt#Y@R^cv$e zR5q>e7L(0--|s6|d%ab;TXM4(q~tF6FKQ%`2Z1IOhmuccWB31f8ib;B>1pq(I>W?@ z!Rmse&drl_q9iL1r8O*4V;)B9SqwEfU>o|^z)+(Wwd6D8Pg5VGN8J2W6L)PXf&ztz zZH1qm!?AtxtRX3IAU8bn%tn%ZZC||jQBKi{p4v{n_zv~H?#u5{)mOh9KpsMBXYOmO zkX_k3QV@ye4(%B(P+iQUYy+|y!g_a=3F#AqpFu!+@OXU+dwVCB{t<`kG#fNb;0P^T1wxmc3v zf<-+G5}Zi1q8rMnf}{xvNYVLkdXEmcQiucuM(V`tVEL>bI=QiWKU6T;08{GukkU*} z)f<6uKWsA9V8CRNvV*SoBi-!;Xw+-181!~2PRc>M0CH2#GKj8Qgb-#B{ee0P)+tCF z@Iy+FjTj{Q2jsxOKr(^ELv|o(E6=&D&79CSh^!|m@Fs|SLS{m*t)#HW4nZWU0S`CN zfB_|mKNgHFNfwwiRzglmQlb!bN8)6&&RzU%M*e>pOvaN0$P6YwV?#YkkxnEMwpJ#^ zp;=YpL)O9VQlwmgJ9k9ep&05Et34WSUI!&hld4#;b7^u&PSHra0%gjO=}6j^GUPL? znm>dDB1n}Ga)4}vS0QA$yy}74iDVd2mh2)20NwiHa+X&8IrJ=tqdQ)0%d7`=EUxzX z{HorHGQS+bCE579DyluOqCDv;$7+GEWXM;6^q1#oWk=xW3S^iA@?`}w!d|8fuSj|m z`Kl%e0GXA@STY;>S0KIdK%7) zL5VJ%%;Kg?=K-znx|TtM$|M-ltB|5(Ioz#6>XWm%`2J;85^OLiBNu~KX(@w2`Ry%7 zY6ZLDT2)esYyxvNvZO?en&~`r!u|w$ptQ*0=KYXS4FzBmbgfPt2I= zOHyH14b+AtC|;8UU|H>&B%I8JxSFI2f}E;J29ur8Jd{){6g3J_S`n!hWEfAv%~3Ee zlvw1m+CW@^4WT3yQQZn9Wf7G*47r;CO~c3>V?5H8%rLToLULVF4;jC|4q2slzkneh zI!C#cfVU9N6qrc`1^O^pxy7&^S(+py z>oq(qh7~jf52EThSLtJu8g~ii8 znmXn^klBFT!@eGCNXmOUlou6QC~r|H*@(oWdSx`qVi+r_MynkKE)gn8 z3iRqiDqy9lU5G@;ZkYKwDJLJ$*z*^lZ~cRut)=clqc6xi`K*?@qO|BrB8hxQOJ0U! z-B5qWYi8{V4EmC!AhwY1LJ+mg+s0&7{wp#{PBDys@>e9>KDbckYjWFB=G%kpbfhlz zaEAP}Ct2#K_X;;g923g?UT9g;U~ez-6qbHNnnCJLww3OSg5OeEB{fH>@GbEpXniJq zPu2;0Hjw;_+=m4NaT-X5D&LcCkL zyZe*v_=p^UuFHK$8$kLa%(m}HV}i+deaJvbwJ6GhA4viw7vYoP@uKGA0uBYT3NG344{nVd zS0;@^NHR?colC-*Tr@laLF7$~`ll!OW!Q2x$B*A1i$$$+R0I4tj!c^k+q$&Sbm z5uti}IS{o>ChMglXGPaMsJkV=Zd&cQy|lo>DXojW}AxaeGM8nuLyny z@n)Vb9^75Hqc}eq*4#dxh64qW2hoaMfzt;`GCn3BA{*pqk5oB21WgW;q1cpi7(JBr zP$(Vg+6JGclkepitq;j?FrC!Fdi)6b16RO$giOQ7@gtTgZH1L3=}_3Dr=x6;QQmmOMo87 zSyqKA1X;(48MDX<1nqXpfpzwu4y-5sd=G2U`^-+joi|befmIMtGDor?vn(>|d!cZ1 zZc-eT>S^#D^UylrG`T=;Mrr$p4-Dpr{XGF6B0{UAgX#QJj!JUU0*ah=6GLEH1BEsKA$8x{p{zkgGwJUly3 zqEyJQi@y)4I;#hwU~+LDLMK0hj0@tdg)>D49J@;bpzs|s!D1lL)eXBZLMC?5V~~1>1kz(saP}@K%4R;^4e@1p zQI>%}?v>?%Y;x9a$X|~8dmYFUk|A6*#1TqCF3-zDll!DDiGhgwq_eBen+60roFoNd zR?duCHaC(hOsYEPfx?zmm~-qI{Ffw(zQ@2 zo0OvWDa34%e4zSsQpu=x5c)kwNA(n(evbY_%Ip_N$Qt-{& zakRy(9YR4Mdt}x*lZb2$Ru9;|hpyKfatc`)mP0V?vr3sO;VK=UhnNF$-CL3VN4lf#FB5Rb}K2)Okd{~&e zI#>g5{pqW`oZ;3x+_7SGMC`RweBwo2zn*K!b z`9)dU$H5e3e|g&SJ$b?N1N8qYSGHmEI#*C$s{H>iD&JP2u~eR^YYl7+r2%rBk*ZW3 zQ-)MQ`|7lxoMh3Alm84XQsC>k(X#XMgOMs1gjDKOfwG}Pqk1*kYtU!kcuYW8iKntMt3!cllh3*me9ga z>D`D<{O_y(?M-~4L`xb1w)XT6&V9djphe{*t!vLAwgVlE&YX8gnvRa;<&Jcy{LElN z*G{yEBlT-1ItHu9wxI!TCaWDm>Cfmv8?vW4o6U7qQDp|byn-dh*&U7ks4Bp}| zaN^3*toc)D&=vWergK>FX-S!wzmd2AH{!sKdIE4tB} z9JcnLRbZ0%bH4{IPseG8C81_dI*%-djGh#uy~?wmbQO^wXoGqMHvYhi2j=K0Z2&Qx zYHWvGG{CZc;FTd~J}ab@{)YMxbP4NyOIyhco~yEv1XI4H?dXQl>QO_Gd(*mPI#gQ3 zaz&kO&|wktC)1Uv-Z*$YCTn%|P@0ukz4b8Idj$qH?-dw3RCx+ys~=jR_&)R#3`H*a zkye8Wed%||f~c{yELi~4f1v?zrZ4?XE1r|5Wa`h<73zl5S|2Jd4PW)AdkTH9#To-J zz@)aA8)dNa-S@NtIxAX_m&3e)^n0=k-lu52D|YOgK1*mXp+Y47^=I z{lGk!zK-}%bJ}1b-{g<+?IY|V*8i5F61TV^N2d;Pa5Vo9?{Rd?4|JB+{SX*F6xB30 z!{1G$5>)+>4*C#_>Ot%S`CY2F*j)+4M6E6>eNX z3qhkbl*7K+w4A3FCzY+)EZl5^zh~1SARSY zB6F3wi|IX5bh|pOVT4(>uEIl{#Vx_OdUL}@iFv!ScnO^($Sc1Ly$ZVmOjt%Y$nlzC zngosF==a{+RHKiz(lzV<26n{J63C3pambS$P<=UVX78BFiD;Zn1Km`6r7T-cJ&DG- zI(hh&y@Dp9QHWoO1GoTAtfVC!bo{*%C#h{PXB91u4`r1xaFw9IYT6jHIV{8wvrH$-8$}?0S=tKpW9#79Q?qt@Lm;$suSe~-&J|L|Vx zA1y$#B1EsO?^Q9*T)kKDQKtO&^r|yk#D`k{Z|6K>&Hphrnm<;c*NAw(?;pkG^)Xz= zvi3c0eYo}U3~#8EM8;#^VP69MnQR5?Mw*6tVA@0jJ?0A?MPEHQ+&o{Yz6sTf`~f`^ zX@3MrPo(A19m!6l)#Z~fRF7^QR8OL34QsOu3MSKbL5D{R9L#zWk43Q%+DQCqit)ze zTd86xK+J1kbTWNJRw_SirtO8T*`v@Z5v%oTxEFyHYKcF1;Ks_#tMq~pwV;Y9s9|2I zXIj+E5Rq8{H>57z7HtGktY+ZD&_5Ph#GhcK!hz4M7Wj#RqUM#=bcDF&fEi}-rw}4M zt0J^gg9?!^i$5Obl}cO+tw)jmYk$!C_$aXzZ+`)JZle+Sn6iz2V$M|g6sq1#v4op< z!M$y?vLj#~xSf{6P*2w@|OxR9cNuUw4w(ES^JY%mU?w|>BguZ%3&+elt9+ao1 z9p$T!D%nSMDL4-?n87wo%|Ad9H#wngX7>~)c@=7;xMg2Zb12TTH7%Z4@gJn zbs=m@NB=7pUTBXxM`$Qn1VfI{N^*{7A^w7uM`#Vtt0K~h&0fV*6$|0c5xR&RfpJH1 z@pJ@IkJ3K!g1=RRk_?rPp=%ZkJCD)T4!bfqgLWXhmE9S%u!!-VKaOjl+0ftw{nbNX zEyW4-g_u8aU48KcolhnxBmSfo>K6Y};I+ErS&pTr=t>d|txwa6xScxUG!4SX{L@HX zw5S|J#l=GNE4X-?79(Te^=bMGc>_P4q1D6Q2xbOS5g5nAta`v&9Fe-O6^LxJw$qB+ zs_y!pz&N;ihL#84v(($eP2ip)+HoHSJI~T!XnU4+DLg^VQ41$JevXGNXVHdCh1%z6 z8#(%w&YH>RXjQ0^iLTED_%xGN#XZNUOgd2c@;q%p;c+JY$va7d%@$-~@b}WlTUATA-jo($p z`!+iFxYIuEE=_?(m+7}5X?a=@j0xnpQ)?xGCZ~o(mAjC9h58}p>GyJDR?N3)9UbqN zu>1z~f>(D@o=-xF%d{i83N`Q2Y9S~8i>BVg5(q8s(W?GeN2`3jtGc&bBU12Hr6~xq zuAn%n16BmeUZuX|IW)RT2SP=O^&mHuDH6kj+qaZ>6YGlC;J_ramI7R6rBFA9$*e?3 z^lQO!^wuYt%jYQNgB_xgqe1p$ z7tq{gda}h@L9SVd`B0))^n23#zFZ1yPjuLrOtb ztc1Z~yts*H{PbCP!l+%sMi;;%gwG1Hx(HjP5K7m6Xjh1p62msE5UXO0szVE4b0Jn6 zp|T3G=OjnD<-?W{^0zXvF#D6BLHOFA0c^TQyO2AI>wVNavP7{wpbLrb3o*EmgGZI}IrKM* z=vKc~!;XKx#el_I$oCEdunUxgchtl@775$pA-Q9GZ2|12Y%V#ZbZ6{1Aw9tQm=%Jn zg}6yE2e1Zsq#Hgh!X}Z2%7r4#Y%26vh`FdLdMu8jxSO-!T_EdMSS!KvFGdNsxc4_d zQ6hraXN5&|#4M$DIX0Cb3l5ZLzZ8EYstZ5b;z>OOo2}@{3j*En9DA11s{&dw zJnR=$kyR}Ce&dgnT@~3`LS88IDznxSj`qzOtRy~MYpRcmHCZsGI%=t(YNCmK3bVA- zmYQrRmQ@U8U3?F!3NPUa5+oo4Eh!$3H$R2Bp#qDtJ(Lyov`?GLwI-}B!QrpejNxJ5 zXS$rg{N}7RTEbh++2`I1@>*(W*Mj+CY3~-yik5k03)G|w@Sp{fcM-f>vYja2%88aN zA3;Gr--^}u(KJN%FuPj{SV?nFF<`HtLTeUUP%}I-x+x}WEM8G`N8KFOn$`PYL0W4D zsDs_xu(J3V+lJM_$F4TaKflp}o4Y`*+-bw+GmO+ne~Pc1c&?Og&#n_WPMa5R;Qj=w zCnxDC<+F~gFBKZO<1?HU-s`RM^fNY)pf2|6!kVKl!m7{NVPxcwU$D`{En3Bb3_bv) z8!PM+_nxM?m=7uyyD^2BPdb&M<8)AY_9g2;%xTWqsFzCTuh`eLSlUuC16Oo$@pREl zN+2_@7d|zPY8qtpK%18VIX&2R+{OQ+C#!^u+4)mg5t61%9ftNsj??DVWH|m4`16X)2AMA9(G**@N zFz9WB(5dP)@XsU_uN?_9Bi7*-yaHqY?dkN}9VNKY40g)iOQo8P)pyd@;WLHNfzvbD zsQ=LSJUW=W@33+f+kwlQ?`E_1wTup-XCuzO{v*xXz=$Wrl;(wi0`vP{NKyI$D@ckN zL>RB#$))~K=@u!XB+X$b@TkZebxEmjGtbmh8aJJ`nV)H9`U=>$nc28;yKL?1`$L5V z?3JQr%c@K4iF+j;NEQyd zc{&`6Wxe2W67zt1OPB|qP9yQmU-(-@H*d?7flJsH0uz#$SuchT%UCm<@L?GW!k=(z z85++U;1kDc;0{LXI7~f&iE%hHJ%N33?5l`4tw)YMaKm$cufT}l|U~u^x8m$7Bf=Thr=R?qiVP8Cwk+s&S;tvJZu|+6H z8`rT-usxZTfr;x`A#K$B6lFd7a^9Kmk#>0lYmD)fzyx-{`{H}0uM=1wII_WL!w)8I zWV7MhcvkPjG>zJXG~J13W;cU1cmQ_S8fJkxt5qbAH?gnaGV%`TYL~?P;ip8bk*O7~ zPGl`%PNJi*ND>S3ex?eL^C)1&y50{ylHVV+Tt?@S!_Z@P#{B zNyT$JTStVWyORaO_uE*kdUu1wD!-<(42nm#aal1Jo*Y59bS`W^iYm4NULD2m&V{gJ zI1462oBgaJl00%h>g)ojet>Yj$zA|=4xvxI14>xa28cn`B76L=b%fN)dO*e%Q)wwH~?%$&V!GG^o5vHP!2uhWxV=RE-rtX3h>?y62{#Lc2 z#=T|7UBLxf!4=({;u=ynOgS2BufTy*ta#w$++f^(r#W6PfPAO1hjRg&E2l)BW-n=- zZMoaz7FWZi(^2bfGCQ)1Mw=VYvEuRrBX#B+J6AAms%nF3qC#KP5dQ^x&a;;C11*&d z1ur0*HYi_TV6~Zlj+z@v{V=+XQ=Dv#ey4KaIZVIJf{V!3{|E3t^TF#5t~u&mV>=v! zE^VM|>4{cDEUuPF+-obIpH8`dJU$G{$|ClWb4n!4-76@;Y7}dXYrGz0v-@3NhtA>zEfpy}p69)Yrew)U-u={TuXn$O7=46+b^@ue=wido@&S z5s8E3=9Lirh*?Uds}(RB7OkF|cY5z)lA}a@@1k<+5xUrD*3`p)aau!p+%f41>&z}r z-vzsFb6*(xgq19)qoLx~rrL(53j{vF81|kgtZ+xJy7k!n|9Z+@rGAt|OnCYf5A8g~ zaQg;j!c(;DNOABpu^!hcRz^HyCW13z#B+=w?0~h;(X2m!W6yE*v;(|fu;IwE2`|tX zWxm_3b>zYejO?V%e#!bFMEFbAT|OD9u5Od@`T(22o+04$*BGKr!(;yVmYV3uJ+Ltw z=a@8T^agdU#48-Vnb7?eGB6D`ykf0rTqLC4=7qtIx)8K}jbWrDnD(00G!UibLR20% zt_HkeC-B-;!yMM$K?LOBQhEXG%VGVX^IPTzE&gUc1tv$SH0o2tM2exj_UDNYjQ*Qd zmE*O-`LOM8HWwbf!%E-3Wl=csK7PwOyCuw2t+p%fZMS>J>dV_S@O5B&$G*fJj4FS# z60`F2p5)l9L3{!kHR~1ci?hhT2%m{4UJ{NWR47h)Tf79^pYj@HloCrh#!&EjIODSs zrY`3}7zzEFb38G$7zRjuy`w`xCf>l2!d*#!h%)gpBvZ+kkK^6k0}w3p4!G?5N#qZ#+|nyTcCsoUq=qZ5fA^aAA-Gj zPbJXIn-H=^!3N5be}KBF9ktp7x2BTtVC*;sd-L8GG3)?Q?L?6M)`@u>d|rr$vy(G- z!I3lMN2uk)!{N3MF9~~ncn}Obi|>R;_2H6wR}8fdUB=JYs?mF33DWM9pzWvSx-Yg6 z7W?x+?K0Tn!o2f8fDV9|BAi2GKORE%=5E6GgH4PE^EqOLSLaA4*zU*M%EmiE!P_4> zzX}HX^MH?2m-8PX0^vab@Aev(O1-wLS`Nv+s~(RXqB#yUqY zhN^p{gkm3*I^))z5^LeOeR@&Z8OVPl7+SAilDBZ1tVNocc{EHd$p^?;8p8EJgZbwO z)Ge65z;(BGY1IBBFr+ju0s~6%LgWlsMb-@HPzoQottTFHV54}<5}8F{a%tZ7p9^2< zGJJp?`rk-hC3sSXPq9OOT*&;z6~1CJ&Nk|*8nSMYLU>W0l;w?B!ni#Ub)R%9sK=p- z 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 Jr~kTh{~zTL-jDzQ delta 54363 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 bkU#2>%XF+D+rF+&_gi~*Om|wpdGh}Q$UM-5 diff --git a/src/plugin/tests/context.rs b/src/plugin/tests/context.rs index 7eea0bf0e..9a752903f 100644 --- a/src/plugin/tests/context.rs +++ b/src/plugin/tests/context.rs @@ -288,13 +288,86 @@ fn a_line_diff_fallback_has_unpaired_folds() { assert!(open.contains(&0), "{open:?}"); assert!(!open.contains(&2), "{open:?}"); // Nothing matched the nodes the folds belong to, so the two sides' folds - // are unpaired: the unchanged function below collapses on the side the - // stretch is shaped from, and stays open on the other. + // are unpaired. The unchanged function below still collapses on both + // sides, in one group with the blank line above it. let tree::Pairing::Both { lhs: before, .. } = &sides else { panic!("both sides"); }; assert!(!open_lines(&before.regions).contains(&10), "{open:?}"); - assert!(open.contains(&10), "{open:?}"); + assert!(!open.contains(&10), "{open:?}"); +} + +/// The regions of `source` that start collapsed, with their lines, +/// label and fold state, in document order. +fn collapsed_rows(source: &tree::Source) -> Vec<((u32, u32), String, u32)> { + let mut out = Vec::new(); + walk(&source.regions, &mut |region| { + if region.visibility.collapsed { + out.push(( + (region.range.start.line, region.range.end.line), + region.visibility.label.clone(), + region.fold_state_id, + )); + } + }); + out +} + +#[test] +fn a_fallback_stretch_over_unpaired_folds_collapses_as_one_group_per_side() { + // As `a_stretch_over_whole_folds_collapses_as_one_group`, but past the + // graph limit: the line diff pairs the lines and leaves each side's + // folds unpaired, so the two sides do not match fold for fold. + let unchanged = repeated(0..3, |i| { + format!("def f{i}():\n a = {i}\n b = {i}\n return a + b\n\n") + }); + let before = format!("first = 1\n\n{unchanged}last = 1\n"); + let after = format!("first = 2\n\n{unchanged}last = 2\n"); + let (file, mut sides) = project_with( + "a.py", + &before, + &after, + DiffOptions { + graph_limit: 1, + ..DiffOptions::default() + }, + ); + let fold_states = |source: &tree::Source| { + let mut states = BTreeSet::new(); + walk(&source.regions, &mut |region| { + if is_fold(region) { + states.insert(region.fold_state_id); + } + }); + states + }; + let unshaped = trees(&sides); + assert!(fold_states(lhs(&unshaped)).is_disjoint(&fold_states(rhs(&unshaped)))); + run("context", json!({"lines": 1}), &file, &mut sides); + let sides = trees(&sides); + // One row on each side, rather than one per function and per line + // between them, and on both sides rather than the lhs alone. + let rows = [lhs(&sides), rhs(&sides)].map(collapsed_rows); + let [(lines, label, state)] = &rows[0][..] else { + panic!("one collapsed row: {rows:?}"); + }; + assert_eq!((*lines, label.as_str()), ((2, 16), "14 unchanged lines")); + assert_eq!( + rows[0], rows[1], + "the two sides' groups share fold state {state}, so they open and close together" + ); + for source in [lhs(&sides), rhs(&sides)] { + assert_eq!( + open_lines(&source.regions), + BTreeSet::from([0, 1, 2, 16, 17]) + ); + // Opening the group reveals the functions, not their own folds. + let mut regions = source.regions.clone(); + for region in &mut regions { + region.visibility.collapsed = false; + } + assert_eq!(open_lines(®ions), (0..18).collect()); + } } #[test] @@ -381,6 +454,79 @@ fn a_fold_whose_matched_partner_holds_changes_stays_open() { assert_eq!(collapsed(rhs(&sides)), 0); } +#[test] +fn an_unpaired_fold_alone_in_a_stretch_collapses_on_each_side() { + // Each side's stretch is one whole fold, folds 2 and 5, in fold states + // no region on the other side shares, as after a line diff fallback. + let range = |start: u32, end: u32| types::Range { + start: types::Position { + line: start, + column: 0, + }, + end: types::Position { + line: end, + column: 0, + }, + }; + // A leaf whose id is its alignment id, as on the lhs, or paired with the + // lhs leaf `alignment`, whose fold state it shares. + let leaf = |id: u32, alignment: u32, start: u32, end: u32, changed: bool| tree::Region { + id, + fold_state_id: alignment, + range: range(start, end), + tags: vec![], + visibility: types::Visibility::default(), + node: tree::Node::Leaf { + alignment_id: alignment, + changed: (start..end) + .filter(|_| changed) + .map(|line| types::Span { + line, + start_column: 0, + end_column: 1, + }) + .collect(), + }, + }; + let fold = |id: u32, child: tree::Region| tree::Region { + id, + fold_state_id: id, + range: child.range, + tags: vec![], + visibility: types::Visibility::default(), + node: tree::Node::Fold { + children: vec![child], + }, + }; + let source = |regions| tree::Source { + text: "x\n".repeat(7), + regions, + }; + let mut sides = tree::Pairing::Both { + lhs: source(vec![ + leaf(1, 1, 0, 1, true), + fold(2, leaf(3, 3, 1, 6, false)), + leaf(4, 4, 6, 7, true), + ]), + rhs: source(vec![ + leaf(8, 1, 0, 1, true), + fold(5, leaf(6, 3, 1, 6, false)), + leaf(7, 4, 6, 7, true), + ]), + }; + let (file, _) = project("a.py", "", ""); + run_trees("context", json!({"lines": 0}), &file, &mut sides); + for source in [lhs(&sides), rhs(&sides)] { + assert_eq!( + collapsed_rows(source) + .into_iter() + .map(|(lines, label, _)| (lines, label)) + .collect::>(), + [((1, 6), "5 unchanged lines".to_owned())] + ); + } +} + #[test] fn predicted_group_ids_match_the_applier() { // The stretch starts inside one leaf and ends inside another, with